[Freeswitch-dev] Openzap and CLIP

François Legal devel at thom.fr.eu.org
Wed Feb 24 01:27:31 PST 2010



Oh, you're right. I always forget to attach files ;-) 

François 

On
Wed, 24 Feb 2010 04:13:38 -0500, Michael Jerris  wrote: where? 
  On Feb
24, 2010, at 3:53 AM, François Legal wrote: 

Hello,  

Here comes the
patch. 

The patch fixes the CID for France (and probably other european
countries except maybe england where a specific TAS has to be used), both
for incoming calls and call waiting cases. 

If anybody can try this patch
with US hardware to verify the compatibility. 

I added a new parameter in
openzap.conf (modem-type defaulting to FSK_BELL202) so that modulation can
be specified in config. 

The patch also adds the MWI functionnality on FXS
ports (that meant to also patch mod_voicemail), by using the MWI-Account
parameter in directory set to something like "openzap/x/y".  

Please
comment on this, if any modification need to be made.  

François       

 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.freeswitch.org/pipermail/freeswitch-dev/attachments/20100224/8d15a7dd/attachment-0001.html 
-------------- next part --------------
--- ./libs/openzap/src/.svn/text-base/zap_io.c.svn-base	2010-02-11 11:03:16.000000000 +0100
+++ ./libs/openzap/src/zap_io.c	2010-02-23 17:02:28.371058955 +0100
@@ -645,12 +645,13 @@
 	}
 
 	if (zchan->token_count > 1) {
-		zap_fsk_modulator_init(&fsk_trans, FSK_BELL202, zchan->rate, fsk_data, db_level, 80, 5, 0, zchan_fsk_write_sample, zchan);
+		/*zap_fsk_modulator_init(&fsk_trans, FSK_V23_FORWARD_MODE2, zchan->rate, fsk_data, db_level, 80, 5, 0, zchan_fsk_write_sample, zchan);*/
+		zap_fsk_modulator_init(&fsk_trans, zchan->span->modem_type, zchan->rate, fsk_data, db_level, 80, 5, 0, zchan_fsk_write_sample, zchan);
 		zap_fsk_modulator_send_all((&fsk_trans));
 	} else {
-		zap_fsk_modulator_init(&fsk_trans, FSK_BELL202, zchan->rate, fsk_data, db_level, 180, 5, 300, zchan_fsk_write_sample, zchan);
+		/*zap_fsk_modulator_init(&fsk_trans, FSK_V23_FORWARD_MODE2, zchan->rate, fsk_data, db_level, 180, 5, 300, zchan_fsk_write_sample, zchan);*/
+		zap_fsk_modulator_init(&fsk_trans, zchan->span->modem_type, zchan->rate, fsk_data, db_level, 180, 5, 300, zchan_fsk_write_sample, zchan);
 		zap_fsk_modulator_send_all((&fsk_trans));
-		zchan->buffer_delay = 3500 / zchan->effective_interval;
 	}
 
 	return ZAP_SUCCESS;
@@ -868,6 +869,7 @@
 			case ZAP_CHANNEL_STATE_PROGRESS:				
 			case ZAP_CHANNEL_STATE_GET_CALLERID:
 			case ZAP_CHANNEL_STATE_GENRING:
+			case ZAP_CHANNEL_STATE_MWI:
 				ok = 1;
 				break;
 			default:
@@ -1582,6 +1584,16 @@
 			zap_mutex_unlock(zchan->pre_buffer_mutex);
 		}
 		break;
+
+	case ZAP_COMMAND_SET_MWI:
+		{
+			zchan->pre_buffer_size = ZAP_COMMAND_OBJ_INT;
+
+			status = zap_channel_set_state(zchan, ZAP_CHANNEL_STATE_MWI, 1);
+
+			GOTO_STATUS(done, status);
+		}
+		break;
 	default:
 		break;
 	}
@@ -1925,6 +1937,13 @@
 			}
 		}
 		
+		if (zchan->fds[1] > -1) {
+			if ((write(zchan->fds[1], auxbuf, dlen)) != dlen) {
+				snprintf(zchan->last_error, sizeof(zchan->last_error), "file write error!");
+				return ZAP_FAIL;
+			}
+		}
+
 		return zchan->zio->write(zchan, auxbuf, &dlen);
 	} 
 
@@ -2047,6 +2066,7 @@
 			if (zap_fsk_demod_feed(&zchan->fsk, sln, slen) != ZAP_SUCCESS) {
 				zap_size_t type, mlen;
 				char str[128], *sp;
+				char firstcaller[128] = { '*', '\0'};
 				
 				while(zap_fsk_data_parse(&zchan->fsk, &type, &sp, &mlen) == ZAP_SUCCESS) {
 					*(str+mlen) = '\0';
@@ -2091,9 +2111,29 @@
 							zap_set_string(zchan->caller_data.cid_date, str);
 						}
 						break;
+					case MDMF_FIRST_PHONE_NUM:
+						{
+							if (mlen > sizeof(firstcaller) - 2) {
+								mlen = sizeof(firstcaller) - 2;
+							}
+							zap_set_string(&firstcaller[1], str);
+						}
+						break;
 					}
 				}
 				zap_channel_command(zchan, ZAP_COMMAND_DISABLE_CALLERID_DETECT, NULL);
+				if (! zap_strlen_zero(&firstcaller[1])) {
+					if ((strncmp("private", zchan->caller_data.ani.digits, sizeof ("private") - 1) == 0) ||
+					    (strncmp("unknown", zchan->caller_data.ani.digits, sizeof ("unknown") - 1) == 0)) {
+						zap_set_string(zchan->caller_data.ani.digits, firstcaller);
+						zap_set_string(zchan->caller_data.cid_name, "FWD ");
+						zap_copy_string((char *) (zchan->caller_data.cid_name + 4), & firstcaller[1], strlen(& firstcaller[1]));
+					} else if ((strncmp("private", zchan->caller_data.cid_name, sizeof ("private") - 1) == 0) ||
+					           (strncmp("unknown", zchan->caller_data.cid_name, sizeof ("unknown") - 1) == 0)) {
+						zap_set_string(zchan->caller_data.cid_name, "FWD ");
+						zap_copy_string((char *) (zchan->caller_data.cid_name + 4), & firstcaller[1], strlen(& firstcaller[1]));
+					}
+				}
 			}
 		}
 
@@ -2410,6 +2450,9 @@
 				continue;
 			}
 
+			/* Set default modem type for span */
+			span->modem_type = FSK_BELL202;
+
 			zap_log(ZAP_LOG_DEBUG, "span %d [%s]=[%s]\n", span->span_id, var, val);
 			
 			if (!strcasecmp(var, "trunk_type")) {
@@ -2490,6 +2533,14 @@
 			} else if (!strcasecmp(var, "dtmf_hangup")) {
 				span->dtmf_hangup = strdup(val);
 				span->dtmf_hangup_len = strlen(val);
+			} else if (!strcasecmp(var, "modem-type")) {
+				if (!strcasecmp(val, "FSK_V23_FORWARD_MODE1")) {
+					span->modem_type = FSK_V23_FORWARD_MODE1;
+				} else if (!strcasecmp(val, "FSK_V23_FORWARD_MODE2")) {
+					span->modem_type = FSK_V23_FORWARD_MODE2;
+				} else if (!strcasecmp(val, "FSK_V23_BACKWARD")) {
+					span->modem_type = FSK_V23_BACKWARD;
+				}
 			} else {
 				zap_log(ZAP_LOG_ERROR, "unknown span variable '%s'\n", var);
 			}
--- ./libs/openzap/src/ozmod/ozmod_analog/.svn/text-base/ozmod_analog.c.svn-base	2010-02-11 11:03:15.000000000 +0100
+++ ./libs/openzap/src/ozmod/ozmod_analog/ozmod_analog.c	2010-02-24 09:27:29.079058352 +0100
@@ -256,6 +256,52 @@
 }
 
 /**
+ * \brief Sends message wainting indicator on an analog channel (FSK coded)
+ * \param zchan Channel to send caller id on
+ * \param state indicator value as follows : if bit 0x80 is set, light on indicator - bits 0x7F : amount of messages waiting
+ */
+static void send_mwi(zap_channel_t *zchan, int state)
+{
+	zap_fsk_data_state_t fsk_data;
+	uint8_t databuf[1024] = "";
+	char time_str[9];
+	struct tm tm;
+	time_t now;
+	char indicator;
+	char amount_messages;
+
+	time(&now);
+#ifdef WIN32
+	_tzset();
+	_localtime64_s(&tm, &now);
+#else
+	localtime_r(&now, &tm);
+#endif
+	strftime(time_str, sizeof(time_str), "%m%d%H%M", &tm);
+
+	zap_fsk_data_init(&fsk_data, databuf, sizeof(databuf));
+	zap_fsk_data_add_mdmf(&fsk_data, MDMF_DATETIME, (uint8_t *) time_str, 8);
+					
+	if (state & 0x80) {
+		indicator = 0xFF;
+		amount_messages = state & 0x7F;
+	} else {
+		indicator = 0;
+		amount_messages = state;
+	}
+
+	zap_fsk_data_add_mdmf(&fsk_data, MDMF_MWI, (uint8_t *) & indicator, (uint8_t) sizeof (indicator));
+
+	zap_fsk_data_add_mdmf(&fsk_data, MDMF_AMOUNT_MESSAGES, (uint8_t *) & amount_messages, (uint8_t) sizeof (amount_messages));
+
+	fsk_data.buf[0] = ZAP_CID_TYPE_MWI;
+
+	zap_fsk_data_add_checksum(&fsk_data);
+		
+	zap_channel_send_fsk_data(zchan, &fsk_data, -14);
+}
+
+/**
  * \brief Main thread function for analog channel (outgoing call)
  * \param me Current thread
  * \param obj Channel to run in this thread
@@ -275,6 +321,7 @@
 	uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = 30000;
 	zap_sigmsg_t sig;
 	zap_status_t status;
+	int time = 0;
 	
 	zap_log(ZAP_LOG_DEBUG, "ANALOG CHANNEL thread starting.\n");
 
@@ -346,7 +393,15 @@
 				break;
 			case ZAP_CHANNEL_STATE_GENRING:
 				{
-					if (state_counter > 60000) {
+					if (state_counter == 260) {
+						zap_channel_command(zchan, ZAP_COMMAND_GENERATE_RING_OFF, NULL);
+					} else if (state_counter == 900) {
+						send_caller_id(zchan);
+					} else if (state_counter > 900 && !zap_buffer_inuse(zchan->fsk_buffer) && time == 0) {
+						time = state_counter + 400;
+					} else if (state_counter == time) {
+						zap_channel_command(zchan, ZAP_COMMAND_GENERATE_RING_ON, NULL);
+					} else if (state_counter > 60000) {
 						zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
 					} else if (!zchan->fsk_buffer || !zap_buffer_inuse(zchan->fsk_buffer)) {
 						zap_sleep(interval);
@@ -354,6 +409,18 @@
 					}
 				}
 				break;
+			case ZAP_CHANNEL_STATE_MWI:
+				{
+					if (state_counter == 400) {
+						zap_channel_command(zchan, ZAP_COMMAND_GENERATE_RING_OFF, NULL);
+					} else if (state_counter == 1100) {
+						send_mwi(zchan, zchan->pre_buffer_size);
+					} else if (state_counter > 1200 && !zap_buffer_inuse(zchan->fsk_buffer)) {
+						zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
+						continue;
+					}
+				}
+				break;
 			case ZAP_CHANNEL_STATE_DIALTONE:
 				{
 					if (!zap_test_flag(zchan, ZAP_CHANNEL_HOLD) && state_counter > 10000) {
@@ -397,7 +464,15 @@
 				{
 					int done = 0;
 					
-					if (zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] == 1) {
+					if (state_counter == 760) {
+						ts.user_data = zchan->fsk_buffer;
+						teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_CALLWAITING_CAS]);
+						ts.user_data = dt_buffer;
+					} else if (state_counter == 1100) {
+						send_caller_id(zchan);
+					} else 
+					
+					/*if (zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] == 1) {
 						send_caller_id(zchan);
 						zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]++;
 					} else if (state_counter > 600 && !zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]) {
@@ -405,7 +480,8 @@
 						zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]++;
 					} else if (state_counter > 1000 && !zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]) {
 						done = 1;
-					} else if (state_counter > 10000) {
+					} else*/ if (state_counter > 10000) {
+						/*
 						if (zchan->fsk_buffer) {
 							zap_buffer_zero(zchan->fsk_buffer);
 						} else {
@@ -414,7 +490,7 @@
 						
 						ts.user_data = zchan->fsk_buffer;
 						teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_CALLWAITING_SAS]);
-						ts.user_data = dt_buffer;
+						ts.user_data = dt_buffer;*/
 						done = 1;
 					}
 
@@ -533,7 +609,7 @@
 					
 					ts.user_data = zchan->fsk_buffer;
 					teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_CALLWAITING_SAS]);
-					teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_CALLWAITING_CAS]);
+					/*teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_CALLWAITING_CAS]);*/
 					ts.user_data = dt_buffer;
 				}
 				break;
@@ -541,8 +617,8 @@
 				{
 					zap_sigmsg_t sig;
 
-					send_caller_id(zchan);
 					zap_channel_command(zchan, ZAP_COMMAND_GENERATE_RING_ON, NULL);
+					time = 0;
 
 					memset(&sig, 0, sizeof(sig));
 					sig.chan_id = zchan->chan_id;
@@ -553,6 +629,17 @@
 					
 				}
 				break;
+			case ZAP_CHANNEL_STATE_MWI:
+				{
+					if (zchan->fsk_buffer) {
+						zap_buffer_zero(zchan->fsk_buffer);
+					} else {
+						zap_buffer_create(&zchan->fsk_buffer, 128, 128, 0);
+					}
+
+					zap_channel_command(zchan, ZAP_COMMAND_GENERATE_RING_ON, NULL);
+				}
+				break;
 			case ZAP_CHANNEL_STATE_GET_CALLERID:
 				{
 					memset(&zchan->caller_data, 0, sizeof(zchan->caller_data));
@@ -671,6 +758,8 @@
 					zap_log(ZAP_LOG_ERROR, "No Digits to send!\n");
 					zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_BUSY);
 				} else {
+					/* I seem to have some trouble when dialing as soon as dialtone is detected */
+					usleep (400000);
 					if (zap_channel_command(zchan, ZAP_COMMAND_SEND_DTMF, zchan->caller_data.ani.digits) != ZAP_SUCCESS) {
 						zap_log(ZAP_LOG_ERROR, "Send Digits Failed [%s]\n", zchan->last_error);
 						zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_BUSY);
--- ./libs/openzap/src/include/.svn/text-base/openzap.h.svn-base	2010-02-11 11:03:16.000000000 +0100
+++ ./libs/openzap/src/include/openzap.h	2010-02-23 17:00:23.540058087 +0100
@@ -585,6 +585,7 @@
 	int suggest_chan_id;
 	zap_state_map_t *state_map;
 	struct zap_span *next;
+	fsk_modem_types_t modem_type;
 };
 
 
@@ -636,6 +637,7 @@
 OZ_DECLARE(int) zap_fsk_demod_init(zap_fsk_data_state_t *state, int rate, uint8_t *buf, size_t bufsize);
 OZ_DECLARE(zap_status_t) zap_fsk_data_init(zap_fsk_data_state_t *state, uint8_t *data, uint32_t datalen);
 OZ_DECLARE(zap_status_t) zap_fsk_data_add_mdmf(zap_fsk_data_state_t *state, zap_mdmf_type_t type, const uint8_t *data, uint32_t datalen);
+OZ_DECLARE(zap_status_t) zap_fsk_data_add_mwi(zap_fsk_data_state_t *state, zap_mdmf_type_t type, const uint8_t *data, uint32_t datalen);
 OZ_DECLARE(zap_status_t) zap_fsk_data_add_checksum(zap_fsk_data_state_t *state);
 OZ_DECLARE(zap_status_t) zap_fsk_data_add_sdmf(zap_fsk_data_state_t *state, const char *date, char *number);
 OZ_DECLARE(zap_status_t) zap_channel_outgoing_call(zap_channel_t *zchan);
--- ./src/include/.svn/text-base/zap_types.h.svn-base	2010-02-11 11:03:16.000000000 +0100
+++ ./src/include/zap_types.h	2010-02-17 14:34:58.427058956 +0100
@@ -81,7 +81,8 @@
 
 typedef enum {
 	ZAP_CID_TYPE_SDMF = 0x04,
-	ZAP_CID_TYPE_MDMF = 0x80
+	ZAP_CID_TYPE_MDMF = 0x80,
+	ZAP_CID_TYPE_MWI = 0x82
 } zap_cid_type_t;
 
 typedef enum {
@@ -92,9 +93,16 @@
 	MDMF_PHONE_NAME = 7,
 	MDMF_NO_NAME = 8,
 	MDMF_ALT_ROUTE = 9,
-	MDMF_INVALID = 10
+	MDMF_MWI = 11,
+	MDMF_MESSAGE_ID = 13,
+	MDMF_LAST_VM_FROM = 14,
+	MDMF_CALL_TYPE = 17,
+	MDMF_FIRST_PHONE_NUM = 18,
+	MDMF_AMOUNT_MESSAGES = 19,
+	MDMF_FWD_TYPE = 21,
+	MDMF_INVALID = 22
 } zap_mdmf_type_t;
-#define MDMF_STRINGS "X", "DATETIME", "PHONE_NUM", "DDN", "NO_NUM", "X", "X", "PHONE_NAME", "NO_NAME", "ALT_ROUTE", "INVALID"
+#define MDMF_STRINGS "X", "DATETIME", "PHONE_NUM", "DDN", "NO_NUM", "X", "X", "PHONE_NAME", "NO_NAME", "ALT_ROUTE", "X", "MWI", "X", "MESSAGE_ID", "LAST_VM_FROM", "X", "X", "CALL_TYPE", "FIRST_PHONE_NUM", "AMOUNT_OF_MESSAGES", "X", "FWD_TYPE", "INVALID"
 ZAP_STR2ENUM_P(zap_str2zap_mdmf_type, zap_mdmf_type2str, zap_mdmf_type_t)
 
 #define ZAP_TONEMAP_LEN 128
@@ -284,7 +292,8 @@
 	ZAP_COMMAND_FLUSH_RX_BUFFERS,
 	ZAP_COMMAND_FLUSH_BUFFERS,
 	ZAP_COMMAND_SET_PRE_BUFFER_SIZE,
-	ZAP_COMMAND_COUNT
+	ZAP_COMMAND_COUNT,
+	ZAP_COMMAND_SET_MWI
 } zap_command_t;
 
 typedef enum {
@@ -316,7 +325,8 @@
 	ZAP_CHANNEL_FEATURE_CODECS = (1 << 2),
 	ZAP_CHANNEL_FEATURE_INTERVAL = (1 << 3),
 	ZAP_CHANNEL_FEATURE_CALLERID = (1 << 4),
-	ZAP_CHANNEL_FEATURE_PROGRESS = (1 << 5)
+	ZAP_CHANNEL_FEATURE_PROGRESS = (1 << 5),
+	ZAP_CHANNEL_FEATURE_FAX_DETECT = (1 << 6)
 } zap_channel_feature_t;
 
 typedef enum {
@@ -341,11 +351,12 @@
 	ZAP_CHANNEL_STATE_CANCEL,
 	ZAP_CHANNEL_STATE_HANGUP,
 	ZAP_CHANNEL_STATE_HANGUP_COMPLETE,
+	ZAP_CHANNEL_STATE_MWI,
 	ZAP_CHANNEL_STATE_INVALID
 } zap_channel_state_t;
 #define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \
 		"RING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \
-		"RESTART", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", "HANGUP", "HANGUP_COMPLETE", "INVALID"
+		"RESTART", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", "HANGUP", "HANGUP_COMPLETE", "MWI", "INVALID"
 ZAP_STR2ENUM_P(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t)
 
 typedef enum {
--- ./libs/openzap/mod_openzap/.svn/text-base/mod_openzap.c.svn-base	2010-02-11 11:03:16.000000000 +0100
+++ ./libs/openzap/mod_openzap/mod_openzap.c	2010-02-23 19:02:31.071059153 +0100
@@ -1901,6 +1901,95 @@
 
 }
 
+static switch_status_t zap_send_mwi (int span_no, int chan_no, int messages)
+{
+	zap_span_t *span;
+	zap_channel_t *chan = NULL;
+	
+	if ((span = SPAN_CONFIG[span_no].span) == NULL) {
+		zap_log(ZAP_LOG_ERROR, "invalid span %d\n", span_no);
+		return (ZAP_FAIL);
+	} 
+
+	if (chan_no > span->chan_count || span->channels[chan_no] == NULL) {
+		zap_log(ZAP_LOG_ERROR, "invalid channel %d:%d\n", span_no, chan_no);
+		return (ZAP_FAIL);
+	} 
+
+	while (span->channels[chan_no]->state != ZAP_CHANNEL_STATE_DOWN) {
+		sleep (2);
+	}
+
+	sleep (2);
+
+	zap_channel_open(span_no, chan_no, &chan);
+	zap_channel_outgoing_call(chan);
+	zap_channel_command(chan, ZAP_COMMAND_SET_MWI, &messages);
+	zap_channel_init(chan);
+
+	return (ZAP_SUCCESS);
+}
+
+static void mod_openzap_mwi_handler(switch_event_t *event)
+{
+	char *account, *amount;
+	char *seek_ptr, *end_ptr;
+	int span_no = 0;
+	int chan_no = 0;
+	int amount_new = 0;
+	int amount_saved = 0;
+
+	switch_assert(event);
+
+	if (event->event_id == SWITCH_EVENT_MESSAGE_WAITING) {
+
+		if (!(account = switch_event_get_header(event, "mwi-message-account"))) {
+			zap_log(ZAP_LOG_ERROR, "Missing required Header 'MWI-Message-Account'\n");
+			return;
+		}
+
+		if (strncmp ("openzap/", account, sizeof("openzap/") - 1)) {
+			zap_log(ZAP_LOG_DEBUG, "The MWI-Account is not for openzap notification : %s\n", account);
+			return;
+		}
+
+		if ((seek_ptr = strchr(account, '/')) == NULL) {
+			span_no = chan_no = 0;
+		} else if ((end_ptr = strchr (++seek_ptr, '/')) == NULL) {
+			span_no = atoi(seek_ptr);
+			chan_no = 0;
+		} else {
+			span_no = atoi(seek_ptr);
+			chan_no = atoi(++end_ptr);
+		}
+
+		if (!(amount = switch_event_get_header(event, "mwi-voice-message"))) {
+			zap_log(ZAP_LOG_ERROR, "Missing required Header 'mwi-voice-message'\n");
+			return;
+		}
+
+		if ((seek_ptr = strchr(amount, '/')) == NULL) {
+			amount_new = atoi(amount);
+		} else {
+			amount_new = atoi(amount);
+			amount_saved = atoi(++seek_ptr);
+		}
+
+		if (amount_new > 0) {
+			amount_new |= 0x80;
+		} else {
+			amount_new += amount_saved;
+		}
+
+		zap_log(ZAP_LOG_DEBUG, "Sending MWI on [%d:%d] : 0x%X\n", span_no, chan_no, amount_new);
+		zap_send_mwi(span_no, chan_no, amount_new);
+
+	} else {
+		zap_log(ZAP_LOG_ERROR, "Unexpected event %d for this handler\n", event->event_id);
+	}
+
+}
+
 static uint32_t enable_analog_option(const char *str, uint32_t current_options)
 {
 	if (!strcasecmp(str, "3-way")) {
@@ -2720,7 +2809,8 @@
 						   );
 }
 
-#define OZ_SYNTAX "list || dump <span_id> [<chan_id>] || q931_pcap <span_id> on|off [pcapfilename without suffix]" 
+#define OZ_SYNTAX "list || dump <span_id> [<chan_id>] || q931_pcap <span_id> on|off [pcapfilename without suffix]" \
+                  " || trace <span_id> <chan_id> in|out [filename] || mwi <span_id> <chan_id> <mwi data>" 
 SWITCH_STANDARD_API(oz_function)
 {
 	char *mycmd = NULL, *argv[10] = { 0 };
@@ -2909,6 +2999,79 @@
                         goto end;
 		}
 
+	} else if (!strcasecmp(argv[0], "trace")) {
+		int32_t span_id = 0;
+ 		int32_t chan_id = 0;
+                zap_span_t *span;
+		zap_channel_t *chan;
+		const char *pcapfn = NULL;
+		char *tmp_path = NULL;
+		zap_command_t command;
+
+                if (argc < 3) {
+                        stream->write_function(stream, "-ERR Usage: oz trace <span_id> <chan_id> in|out <filename>\n");
+                        goto end;
+                }
+		span_id = atoi(argv[1]);
+		if (!(span_id && (span = SPAN_CONFIG[span_id].span))) {
+                                stream->write_function(stream, "-ERR invalid span\n");
+				goto end;
+                } 
+
+		chan_id = atoi(argv[2]);
+		if (!(chan_id && (chan = span->channels[chan_id]))) {
+                                stream->write_function(stream, "-ERR invalid channel\n");
+				goto end;
+                } 
+
+		if (strcasecmp(argv[3], "in")) {
+			command = ZAP_COMMAND_TRACE_INPUT;
+		} else {
+			if (strcasecmp(argv[3], "out")) {
+				command = ZAP_COMMAND_TRACE_OUTPUT;
+			} else {
+                                stream->write_function(stream, "-ERR invalid recording direction\n");
+				goto end;
+			}
+		}
+
+		/*Look for a given file name or use default file name*/
+		if (argc > 4) {
+			if(argv[4]){
+				pcapfn=argv[4];
+			}
+		}
+		else {
+			tmp_path=switch_mprintf("%s%szap-%1d-%1d-%s.dmp", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, span_id, chan_id, argv[3]);
+		}
+		if (zap_channel_command(chan, command, tmp_path) != ZAP_SUCCESS) {
+			zap_log(ZAP_LOG_ERROR, "Error couldn't enable trace!\n");
+			goto end;
+		} else {
+			stream->write_function(stream, "+OK\n");
+		}
+	
+	} else if (!strcasecmp(argv[0], "mwi")) {
+		int32_t span_id = 0;
+ 		int32_t chan_id = 0;
+		int32_t indicator = 0;
+
+                if (argc < 4) {
+                        stream->write_function(stream, "-ERR Usage: oz mwi <span_id> <chan_id> <0|1>\n");
+                        goto end;
+                }
+		span_id = atoi(argv[1]);
+		chan_id = atoi(argv[2]);
+		indicator = atoi(argv[3]);
+
+		zap_log(ZAP_LOG_DEBUG, "Sending MWI on [%d:%d] : 0x%X\n", span_id, chan_id, indicator);
+
+		if (zap_send_mwi(span_id, chan_id, indicator) == ZAP_SUCCESS) {
+			stream->write_function(stream, "+OK\n");
+		} else {
+			stream->write_function(stream, "-ERR\n");
+		}
+
 	} else {
 		char *rply = zap_api_execute(cmd, NULL);
 		
@@ -2978,6 +3141,10 @@
 	openzap_endpoint_interface->io_routines = &openzap_io_routines;
 	openzap_endpoint_interface->state_handler = &openzap_state_handlers;
 	
+	if (switch_event_bind(openzap_endpoint_interface->interface_name, SWITCH_EVENT_MESSAGE_WAITING, SWITCH_EVENT_SUBCLASS_ANY, mod_openzap_mwi_handler, NULL) != SWITCH_STATUS_SUCCESS) {
+		zap_log(ZAP_LOG_ERROR, "Error binding MWI to OpenZAP\n");
+	}	
+
 	SWITCH_ADD_API(commands_api_interface, "oz", "OpenZAP commands", oz_function, OZ_SYNTAX);
 
 	SWITCH_ADD_APP(app_interface, "disable_ec", "Disable Echo Canceller", "Disable Echo Canceller", disable_ec_function, "", SAF_NONE);
@@ -2988,6 +3155,8 @@
 
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_openzap_shutdown)
 {
+	switch_event_unbind_callback(mod_openzap_mwi_handler);
+
 	zap_global_destroy();
 
 	// this breaks pika but they are MIA so *shrug*
--- .src/mod/applications/mod_voicemail/.svn/text-base/mod_voicemail.c.svn-base	2010-02-11 11:00:12.000000000 +0100
+++ .src/mod/applications/mod_voicemail/mod_voicemail.c	2010-02-19 09:49:06.344058424 +0100
@@ -1653,7 +1661,7 @@
 }
 
 
-static void update_mwi(vm_profile_t *profile, const char *id, const char *domain_name, const char *myfolder)
+static void update_mwi(vm_profile_t *profile, const char *id, const char *domain_name, const char *myfolder, const char *mwi_account)
 {
 	const char *yn = "no";
 	int total_new_messages = 0;
@@ -1673,13 +1681,16 @@
 		yn = "yes";
 	}
 	switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "MWI-Messages-Waiting", yn);
-	switch_event_add_header(event, SWITCH_STACK_BOTTOM, "MWI-Message-Account", "%s@%s", id, domain_name);
+	if (mwi_account == NULL) {
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "MWI-Message-Account", "%s@%s", id, domain_name);
+	} else {
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "MWI-Message-Account", "%s", mwi_account);
+	}
 	switch_event_add_header(event, SWITCH_STACK_BOTTOM, "MWI-Voice-Message", "%d/%d (%d/%d)", total_new_messages, total_saved_messages,
 							total_new_urgent_messages, total_saved_urgent_messages);
 	switch_event_fire(&event);
 }
 
-
 #define FREE_DOMAIN_ROOT() if (x_domain_root) switch_xml_free(x_domain_root); x_user = x_domain = x_domain_root = NULL
 
 
@@ -1703,6 +1714,7 @@
 	int total_saved_urgent_messages = 0;
 	int heard_auto_saved = 0, heard_auto_new = 0;
 	char *vm_email = NULL, *email_addr = NULL;
+	char *mwi_account = NULL;
 	char *convert_cmd = profile->convert_cmd;
 	char *convert_ext = profile->convert_ext;
 	char *vm_storage_dir = NULL;
@@ -1872,7 +1884,7 @@
 				vm_execute_sql(profile, sql, profile->mutex);
 				vm_check_state = VM_CHECK_FOLDER_SUMMARY;
 
-				update_mwi(profile, myid, domain_name, myfolder);
+				update_mwi(profile, myid, domain_name, myfolder, mwi_account);
 			}
 			break;
 		case VM_CHECK_CONFIG:
@@ -2145,6 +2157,8 @@
 
 					} else if (!strcasecmp(var, "timezone")) {
 						switch_channel_set_variable(channel, var, val);
+					} else if (!strcasecmp(var, "MWI-Account")) {
+						mwi_account = switch_core_session_strdup(session, val);
 					}
 
 				}
@@ -2279,6 +2293,7 @@
 	char *vm_notify_email = NULL;
 	char *email_addr = NULL;
 	char *vm_timezone = NULL;
+	char *mwi_account = NULL;
 	int send_mail = 0;
 	int send_main = 0;
 	int send_notify = 0;
@@ -2351,10 +2366,12 @@
 			convert_ext = switch_core_strdup(pool, val);
 		} else if (!strcasecmp(var, "timezone")) {
 			vm_timezone = switch_core_strdup(pool, val);
+		} else if (!strcasecmp(var, "MWI-Account")) {
+			mwi_account = switch_core_strdup(pool, val);
 		}
 		/*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send mail is %d, var is %s\n", send_mail, var); */
 	}
-
+	
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deliver VM to %s@%s\n", myid, domain_name);
 
 	if (!zstr(vm_storage_dir)) {
@@ -2415,7 +2432,7 @@
 		vm_execute_sql(profile, usql, profile->mutex);
 		switch_safe_free(usql);
 
-		update_mwi(profile, myid, domain_name, myfolder);
+		update_mwi(profile, myid, domain_name, myfolder, mwi_account);
 	}
 
 	if (send_mail && !zstr(vm_email) && switch_file_exists(file_path, pool) == SWITCH_STATUS_SUCCESS) {
@@ -3569,6 +3586,8 @@
 	char *sql;
 	struct holder holder;
 	char *ref = NULL;
+	char *mwi_account = NULL;
+	switch_xml_t x_domain = NULL, x_domain_root = NULL, x_user = NULL, x_params, x_param;
 
 	if (stream->param_event) {
 		ref = switch_event_get_header(stream->param_event, "http-referer");
@@ -3586,7 +3605,22 @@
 	vm_execute_sql(profile, sql, profile->mutex);
 	free(sql);
 
-	update_mwi(profile, user, domain, myfolder);
+	if (switch_xml_locate_user("id", user, domain, NULL, &x_domain_root, &x_domain, &x_user, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+		stream->write_function(stream, "Can't find user [%s@%s]\n", user, domain);
+	} else {
+		if ((x_params = switch_xml_child(x_user, "params"))) {
+			for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
+				const char *var = switch_xml_attr_soft(x_param, "name");
+				const char *val = switch_xml_attr_soft(x_param, "value");
+
+				if (!strcasecmp(var, "MWI-Account")) {
+					mwi_account = switch_core_strdup(profile->pool, val);
+				}
+			}
+		}
+	}
+
+	update_mwi(profile, user, domain, myfolder, mwi_account);
 
 	if (ref) {
 		stream->write_function(stream, "Content-type: text/html\n\n<h2>Message Deleted</h2>\n" "<META http-equiv=\"refresh\" content=\"1;URL=%s\">", ref);


More information about the FreeSWITCH-dev mailing list