Revision
14632
Author
gmaruzz
Date
2009-08-25 05:07:07 -0500 (Tue, 25 Aug 2009)

Log Message

celliax: hangs up. Race between read and write on serial, heh. That's why took so much effort implement locking. OK, we'll reinstate it... :-) 

Modified Paths

Diff

Modified: freeswitch/branches/gmaruzz/mod_celliax/celliax.h (14631 => 14632)


--- freeswitch/branches/gmaruzz/mod_celliax/celliax.h	2009-08-25 08:46:59 UTC (rev 14631)
+++ freeswitch/branches/gmaruzz/mod_celliax/celliax.h	2009-08-25 10:07:07 UTC (rev 14632)
@@ -494,3 +494,6 @@
 int celliax_answer(private_t * tech_pvt);
 int celliax_serial_answer(private_t * tech_pvt);
 int celliax_serial_answer_AT(private_t * tech_pvt);
+int celliax_serial_hangup(private_t * tech_pvt);
+int celliax_serial_hangup_AT(private_t * tech_pvt);
+int celliax_hangup(private_t * tech_pvt);

Modified: freeswitch/branches/gmaruzz/mod_celliax/celliax_protocol.c (14631 => 14632)


--- freeswitch/branches/gmaruzz/mod_celliax/celliax_protocol.c	2009-08-25 08:46:59 UTC (rev 14631)
+++ freeswitch/branches/gmaruzz/mod_celliax/celliax_protocol.c	2009-08-25 10:07:07 UTC (rev 14632)
@@ -2095,9 +2095,11 @@
         if (option_debug > 1)
           DEBUGA_SKYPE("|%s| CALLFLOW_CALL_NOCARRIER\n", SKYPIAX_P_LOG,
                     tech_pvt->line_array.result[i]);
-        if (tech_pvt->interface_state != SKYPIAX_STATE_DOWN && tech_pvt->owner) {
-          tech_pvt->owner->hangupcause = SKYPIAX_CAUSE_FAILURE;
-          celliax_queue_control(tech_pvt->owner, SKYPIAX_CONTROL_HANGUP);
+        if (tech_pvt->interface_state != SKYPIAX_STATE_DOWN) {
+			//cicopet
+		celliax_hangup(tech_pvt);
+          //tech_pvt->owner->hangupcause = SKYPIAX_CAUSE_FAILURE;
+          //celliax_queue_control(tech_pvt->owner, SKYPIAX_CONTROL_HANGUP);
         } else {
           ERRORA("Why NO CARRIER now?\n", SKYPIAX_P_LOG);
         }
@@ -3224,6 +3226,22 @@
   return 0;
 }
 
+int celliax_serial_hangup(private_t * tech_pvt)
+{
+  if (tech_pvt->controldevprotocol == PROTOCOL_AT)
+    return celliax_serial_hangup_AT(tech_pvt);
+#ifdef CELLIAX_FBUS2
+  if (tech_pvt->controldevprotocol == PROTOCOL_FBUS2)
+    return celliax_serial_hangup_FBUS2(tech_pvt);
+#endif /* CELLIAX_FBUS2 */
+#ifdef CELLIAX_CVM
+  if (tech_pvt->controldevprotocol == PROTOCOL_CVM_BUSMAIL)
+    return celliax_serial_hangup_CVM_BUSMAIL(tech_pvt);
+#endif /* CELLIAX_CVM */
+  return -1;
+}
+
+
 int celliax_serial_hangup_AT(private_t * tech_pvt)
 {
   int res;
@@ -3404,8 +3422,156 @@
   return res;
 }
 
+/*! \brief  Hangup celliax call
+ * Part of PBX interface, called from ast_hangup */
 
+int celliax_hangup(private_t * tech_pvt)
+{
+
+  /* if there is not celliax pvt why we are here ? */
+  if (!tech_pvt) {
+    ERRORA("Asked to hangup channel not connected\n", SKYPIAX_P_LOG);
+    return 0;
+  }
+
+  if (option_debug) {
+    DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+  }
+
 #ifdef NOTDEF
+  /* shutdown the serial monitoring thread */
+  if (tech_pvt->controldev_thread && (tech_pvt->controldev_thread != SKYPIAX_PTHREADT_NULL)
+      && (tech_pvt->controldev_thread != SKYPIAX_PTHREADT_STOP)) {
+    if (pthread_cancel(tech_pvt->controldev_thread)) {
+      ERRORA("controldev_thread pthread_cancel failed, maybe he killed himself?\n",
+             SKYPIAX_P_LOG);
+    }
+    /* push it, maybe is stuck in a select or so */
+    if (pthread_kill(tech_pvt->controldev_thread, SIGURG)) {
+      DEBUGA_SKYPE("controldev_thread pthread_kill failed, no problem\n", SKYPIAX_P_LOG);
+    }
+#ifndef __CYGWIN__              /* under cygwin, this seems to be not reliable, get stuck at times */
+    /* wait for it to die */
+    if (pthread_join(tech_pvt->controldev_thread, NULL)) {
+      ERRORA("controldev_thread pthread_join failed, BAD\n", SKYPIAX_P_LOG);
+    }
+#else /* __CYGWIN__ */
+/* allow the serial thread to die */
+    usleep(300000);             //300msecs
+#endif /* __CYGWIN__ */
+  }
+  tech_pvt->controldev_thread = SKYPIAX_PTHREADT_NULL;
+#endif// NOTDEF
+
+
+  if (tech_pvt->controldevprotocol != PROTOCOL_NO_SERIAL) {
+    if (tech_pvt->interface_state != SKYPIAX_STATE_DOWN) {
+      /* actually hangup through the serial port */
+      if (tech_pvt->controldevprotocol != PROTOCOL_NO_SERIAL) {
+        int res;
+        res = celliax_serial_hangup(tech_pvt);
+        if (res) {
+          ERRORA("celliax_serial_hangup error: %d\n", SKYPIAX_P_LOG, res);
+          if (option_debug) {
+            DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+          }
+          return -1;
+        }
+      }
+
+      while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN) {
+        usleep(10000);          //10msec
+      }
+      if (tech_pvt->interface_state != SKYPIAX_STATE_DOWN) {
+        ERRORA("call hangup failed\n", SKYPIAX_P_LOG);
+        return -1;
+      } else {
+        DEBUGA_SKYPE("call hungup\n", SKYPIAX_P_LOG);
+      }
+    }
+  } else {
+    tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+    tech_pvt->phone_callflow = CALLFLOW_CALL_IDLE;
+  }
+
+		switch_set_flag(tech_pvt, TFLAG_HANGUP);
+#ifdef NOTDEF
+  /* if there is a dsp struct alloced, free it */
+  if (tech_pvt->dsp) {
+    ast_dsp_free(tech_pvt->dsp);
+    tech_pvt->dsp = NULL;
+  }
+#ifndef __CYGWIN__
+#ifdef CELLIAX_ALSA
+/* restart alsa */
+  snd_pcm_drop(tech_pvt->alsap);
+  snd_pcm_prepare(tech_pvt->alsap);
+
+  snd_pcm_prepare(tech_pvt->alsac);
+  snd_pcm_start(tech_pvt->alsac);
+#endif /* CELLIAX_ALSA */
+
+#endif /* __CYGWIN__ */
+#ifdef CELLIAX_PORTAUDIO
+  speex_echo_state_reset(tech_pvt->stream->echo_state);
+#endif // CELLIAX_PORTAUDIO
+
+  /* re-init the serial port, be paranoid */
+  if (tech_pvt->controldevprotocol != PROTOCOL_NO_SERIAL) {
+    tech_pvt->controldevfd = celliax_serial_init(p, tech_pvt->controldevice_speed);
+    if (tech_pvt->controldevfd < 1) {
+      ERRORA("bad, bad, bad\n", SKYPIAX_P_LOG);
+      if (option_debug) {
+        DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+      }
+      return -1;
+    }
+  }
+#ifndef ASTERISK_VERSION_1_4
+  /* subtract one to the usage count of Celliax-type channels */
+  LOKKA(&celliax_usecnt_lock);
+  celliax_usecnt--;
+  if (celliax_usecnt < 0)
+    ERRORA("Usecnt < 0???\n", SKYPIAX_P_LOG);
+  UNLOCKA(&celliax_usecnt_lock);
+  ast_update_use_count();
+#else /* ASTERISK_VERSION_1_4 */
+	ast_module_unref(ast_module_info->self);
+#endif /* ASTERISK_VERSION_1_4 */
+
+  /* our celliax pvt interface is no more part of a channel */
+  tech_pvt->owner = NULL;
+  /* our channel has no more this celliax pvt interface to manage */
+  c->tech_pvt = NULL;
+  /* set the channel state to DOWN, eg. available, not in active use */
+  if (ast_setstate(c, SKYPIAX_STATE_DOWN)) {
+    ERRORA("ast_setstate failed, BAD\n", SKYPIAX_P_LOG);
+    if (option_debug) {
+      DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+    }
+    return -1;
+  }
+
+  if (option_debug)
+    DEBUGA_PBX("Hanged Up\n", SKYPIAX_P_LOG);
+  /* restart the monitor thread, so it can recheck which interfaces it have to watch during its loop (the interfaces that are not owned by channels) */
+  if (celliax_restart_monitor()) {
+    ERRORA("celliax_restart_monitor failed, BAD\n", SKYPIAX_P_LOG);
+    if (option_debug) {
+      DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+    }
+    return -1;
+  }
+
+#endif// NOTDEF
+  if (option_debug) {
+    DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+  }
+  return 0;
+}
+
+
+#ifdef NOTDEF
 int celliax_serial_call_AT(private_t * tech_pvt, char *dstr)
 {
   int res;

Modified: freeswitch/branches/gmaruzz/mod_celliax/mod_celliax.c (14631 => 14632)


--- freeswitch/branches/gmaruzz/mod_celliax/mod_celliax.c	2009-08-25 08:46:59 UTC (rev 14631)
+++ freeswitch/branches/gmaruzz/mod_celliax/mod_celliax.c	2009-08-25 10:07:07 UTC (rev 14632)
@@ -252,6 +252,7 @@
 		ERRORA("celliax_codec FAILED\n", SKYPIAX_P_LOG);
 		return SWITCH_STATUS_FALSE;
 	}
+switch_clear_flag(tech_pvt, TFLAG_HANGUP);	
 	DEBUGA_SKYPE("celliax_codec SUCCESS\n", SKYPIAX_P_LOG);
 	return SWITCH_STATUS_SUCCESS;
 }
@@ -472,7 +473,6 @@
 {
 	switch_channel_t *channel = NULL;
 	private_t *tech_pvt = NULL;
-	char msg_to_skype[256];
 
 
 	channel = switch_core_session_get_channel(session);
@@ -491,14 +491,10 @@
 
 	switch_clear_flag(tech_pvt, TFLAG_IO);
 	switch_clear_flag(tech_pvt, TFLAG_VOICE);
-	//switch_set_flag(tech_pvt, TFLAG_HANGUP);
+	switch_set_flag(tech_pvt, TFLAG_HANGUP);
 
-	if (strlen(tech_pvt->skype_call_id)) {
-		//switch_thread_cond_signal(tech_pvt->cond);
-		DEBUGA_SKYPE("hanging up skype call: %s\n", SKYPIAX_P_LOG, tech_pvt->skype_call_id);
-		sprintf(msg_to_skype, "ALTER CALL %s HANGUP", tech_pvt->skype_call_id);
-		celliax_signaling_write(tech_pvt, msg_to_skype);
-	}
+	celliax_hangup(tech_pvt);
+
 	//memset(tech_pvt->session_uuid_str, '\0', sizeof(tech_pvt->session_uuid_str));
 	//*tech_pvt->session_uuid_str = '\0';
 	DEBUGA_SKYPE("%s CHANNEL HANGUP\n", SKYPIAX_P_LOG, tech_pvt->name);
@@ -646,6 +642,10 @@
 	tech_pvt->read_frame.flags = SFF_NONE;
 	*frame = NULL;
 
+		if (switch_test_flag(tech_pvt, TFLAG_HANGUP)) {
+		return SWITCH_STATUS_FALSE;
+		}
+
 			goto cng; //FIXME FIXME FIXME
 	if (!celliax_audio_read(tech_pvt)) {