[Asterisk-cvs] asterisk/channels chan_h323.c,1.93,1.94

jeremy at lists.digium.com jeremy at lists.digium.com
Wed Dec 15 18:27:33 CST 2004


Update of /usr/cvsroot/asterisk/channels
In directory mongoose.digium.com:/tmp/cvs-serv32767

Modified Files:
	chan_h323.c 
Log Message:
Major fixes: Fixed deadlock issue, added support for inband call progress and correct Progress Indicator messages, added configurable RTP payload to send RFC2833 DTMF and correct sending of RFC2833 User Input capability, fixed hostname parsing on peers, preliminary support for correct Q.931 cause codes and fixed bindaddr compile warning

Index: chan_h323.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_h323.c,v
retrieving revision 1.93
retrieving revision 1.94
diff -u -d -r1.93 -r1.94
--- chan_h323.c	16 Nov 2004 15:37:56 -0000	1.93
+++ chan_h323.c	15 Dec 2004 23:24:13 -0000	1.94
@@ -81,6 +81,8 @@
 con_established_cb on_connection_established;
 clear_con_cb on_connection_cleared;
 answer_call_cb on_answer_call;
+progress_cb on_progress;
+rfc2833_cb on_set_rfc2833_payload;
 
 /* global debug flag */
 int h323debug;
@@ -91,6 +93,7 @@
 static char *tdesc = "The NuFone Network's Open H.323 Channel Driver";
 static char *config = "h323.conf";
 static char default_context[AST_MAX_EXTENSION] = "default";
+static struct sockaddr_in bindaddr;
 
 /** H.323 configuration values */
 static int h323_signalling_port = 1720;
@@ -99,9 +102,6 @@
 static int gatekeeper_discover = 0;
 static int usingGk = 0;
 static int gkroute = 0;
-static int noFastStart = 0;
-static int noH245Tunneling = 0;
-static int noSilenceSuppression = 0;
 /* Assume we can native bridge by default */
 static int bridging = 1;
 /* Find user by alias (h.323 id) is default, alternative is the incomming call's source IP address*/
@@ -111,6 +111,8 @@
 static int dtmfmode = H323_DTMF_RFC2833;
 static char secret[50];
 
+static call_options_t global_options;
+
 /** Private structure of a OpenH323 channel */
 struct oh323_pvt {
 	ast_mutex_t lock;					/* Channel private lock */
@@ -261,7 +263,7 @@
 	if (user) {
 		memset(user, 0, sizeof(struct oh323_user));
 		strncpy(user->name, name, sizeof(user->name) - 1);
-
+		user->options.dtmfcodec = 101;
 		/* set a native brigding default value */
 		user->bridge = bridging;
 		/* and default context */
@@ -274,17 +276,39 @@
                       } else if (!strcasecmp(v->name, "nat")) {
                               user->nat = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "noFastStart")) {
-				user->noFastStart = ast_true(v->value);
+				user->options.noFastStart = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "noH245Tunneling")) {
-				user->noH245Tunneling = ast_true(v->value);
+				user->options.noH245Tunneling = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "noSilenceSuppression")) {
-				user->noSilenceSuppression = ast_true(v->value);
+				user->options.noSilenceSuppression = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "secret")) {
 				strncpy(user->secret, v->value, sizeof(user->secret) - 1);
 			} else if (!strcasecmp(v->name, "callerid")) {
 				strncpy(user->callerid, v->value, sizeof(user->callerid) - 1);
 			} else if (!strcasecmp(v->name, "accountcode")) {
 				strncpy(user->accountcode, v->value, sizeof(user->accountcode) - 1);
+			} else if (!strcasecmp(v->name, "progress_setup")) {
+				int progress_setup = atoi(v->value);
+				if ((progress_setup != 0) &&
+				   (progress_setup != 1) &&
+				   (progress_setup != 3) &&
+				   (progress_setup != 8)) {
+					ast_log(LOG_WARNING, "Invalid value %d for progress_setup at line %d, assuming 0\n", progress_setup, v->lineno);
+					progress_setup = 0;
+				}
+				user->options.progress_setup = progress_setup;
+			} else if (!strcasecmp(v->name, "progress_alert")) {
+				int progress_alert = atoi(v->value);
+				if ((progress_alert != 0) &&
+				   (progress_alert != 8)) {
+					ast_log(LOG_WARNING, "Invalud value %d for progress_alert at line %d, assuming 0\n", progress_alert, v->lineno);
+					progress_alert = 0;
+				}
+				user->options.progress_alert = progress_alert;
+			} else if (!strcasecmp(v->name, "progress_audio")) {
+				user->options.progress_audio = ast_true(v->value);
+			} else if (!strcasecmp(v->name, "dtmfcodec")) {
+				user->options.dtmfcodec = atoi(v->value);
 			} else if (!strcasecmp(v->name, "host")) {
 				if (!strcasecmp(v->value, "dynamic")) {
 					ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n");
@@ -354,6 +378,8 @@
 		peer->ha = NULL;
 		peer->addr.sin_family = AF_INET;
 		peer->capability = capability;
+		peer->options.dtmfcodec = 101;
+		peer->dtmfmode = H323_DTMF_RFC2833;
 
 		while(v) {
 			if (!strcasecmp(v->name, "bridge")) {
@@ -361,11 +387,33 @@
 			} else if (!strcasecmp(v->name, "nat")) {
 				peer->nat = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "noFastStart")) {
-				peer->noFastStart = ast_true(v->value);
+				peer->options.noFastStart = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "noH245Tunneling")) {
-				peer->noH245Tunneling = ast_true(v->value);
+				peer->options.noH245Tunneling = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "noSilenceSuppression")) {
-				peer->noSilenceSuppression = ast_true(v->value);
+				peer->options.noSilenceSuppression = ast_true(v->value);
+			} else if (!strcasecmp(v->name, "progress_setup")) {
+				int progress_setup = atoi(v->value);
+				if ((progress_setup != 0) &&
+				   (progress_setup != 1) &&
+				   (progress_setup != 3) &&
+				   (progress_setup != 8)) {
+					ast_log(LOG_WARNING, "Invalid value %d for progress_setup at line %d, assuming 0\n", progress_setup, v->lineno);
+					progress_setup = 0;
+				}
+				peer->options.progress_setup = progress_setup;
+			} else if (!strcasecmp(v->name, "progress_alert")) {
+				int progress_alert = atoi(v->value);
+				if ((progress_alert != 0) &&
+				   (progress_alert != 8)) {
+					ast_log(LOG_WARNING, "Invalid value %d for progress_alert at line %d, assuming 0\n", progress_alert, v->lineno);
+					progress_alert = 0;
+				}
+				peer->options.progress_alert = progress_alert;
+			} else if (!strcasecmp(v->name, "progress_audio")) {
+				peer->options.progress_audio = ast_true(v->value);
+			} else if (!strcasecmp(v->name, "dtmfcodec")) {
+				peer->options.dtmfcodec = atoi(v->value);
 			} else if (!strcasecmp(v->name, "dtmfmode")) {
 				if (!strcasecmp(v->value, "inband")) {
 					peer->dtmfmode = H323_DTMF_INBAND;
@@ -415,6 +463,7 @@
  */
 static int oh323_digit(struct ast_channel *c, char digit)
 {
+	ast_log(LOG_DEBUG, "Sending %c...\n", digit);
 	struct oh323_pvt *p = (struct oh323_pvt *) c->pvt->pvt;
 	if (p && p->rtp && (p->dtmfmode & H323_DTMF_RFC2833)) {
 		ast_rtp_senddigit(p->rtp, digit);
@@ -438,8 +487,6 @@
         char addr[INET_ADDRSTRLEN];
         char called_addr[INET_ADDRSTRLEN];
   
-        ast_log(LOG_DEBUG, "Dest is %s\n", dest);
-        
         if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
                 ast_log(LOG_WARNING, "Line is already in use (%s)\n", c->name);
                 return -1;
@@ -448,9 +495,6 @@
         memset(addr, 0, sizeof(addr));
         if (usingGk) {
                 memcpy(addr, dest, strlen(addr));
-                pvt->options.noFastStart = noFastStart;
-                pvt->options.noH245Tunneling = noH245Tunneling;
-                pvt->options.noSilenceSuppression = noSilenceSuppression;
                 pvt->options.port = h323_signalling_port;
         } else {
                 ast_inet_ntoa(addr, sizeof(addr), pvt->sa.sin_addr);
@@ -464,8 +508,8 @@
 	} else {
 		sprintf(called_addr, "%s:%d",addr, pvt->options.port);
 	}
-	ast_log(LOG_DEBUG, "Placing outgoing call to %s\n", dest);
-	res = h323_make_call(dest, &(pvt->cd), pvt->options);
+	ast_log(LOG_DEBUG, "Placing outgoing call to %s, %d\n", called_addr, pvt->options.dtmfcodec);
+	res = h323_make_call(called_addr, &(pvt->cd), &pvt->options);
 	if (res) {
 		ast_log(LOG_NOTICE, "h323_make_call failed(%s)\n", c->name);
 		return -1;
@@ -518,7 +562,7 @@
 
 	/* Start the process if it's not already started */
 	if (!pvt->alreadygone) {
-		if (h323_clear_call((pvt->cd).call_token)) { 
+		if (h323_clear_call((pvt->cd).call_token, c->hangupcause)) { 
 			ast_log(LOG_DEBUG, "ClearCall failed.\n");
 		}
 		pvt->needdestroy = 1;
@@ -617,13 +661,15 @@
 {
 
 	struct oh323_pvt *pvt = (struct oh323_pvt *) c->pvt->pvt;
-	
+
+	ast_log(LOG_DEBUG, "OH323: Indicating %d on %s\n", condition, pvt->cd.call_token);
+
 	switch(condition) {
 	case AST_CONTROL_RINGING:
 		if (c->_state == AST_STATE_RING || c->_state == AST_STATE_RINGING) {
 			h323_send_alerting(pvt->cd.call_token);
  			break;
- 		}		
+ 		}
 		return -1;
 	case AST_CONTROL_PROGRESS:
 		if (c->_state != AST_STATE_UP) {
@@ -656,7 +702,7 @@
 		return -1;
 	ast_mutex_unlock(&pvt->lock);
 	}
-	return 0;
+	return -1;
 }
 
 static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
@@ -681,6 +727,11 @@
 	/* Don't hold a oh323_pvt lock while we allocate a chanel */
 	ast_mutex_unlock(&pvt->lock);
 	ch = ast_channel_alloc(1);
+	/* Update usage counter */
+	ast_mutex_lock(&usecnt_lock);
+	usecnt++;
+	ast_mutex_unlock(&usecnt_lock);
+	ast_update_use_count();
 	ast_mutex_lock(&pvt->lock);
 	if (ch) {
 		snprintf(ch->name, sizeof(ch->name), "H323/%s", host);
@@ -720,12 +771,6 @@
 		/*  Set the owner of this channel */
 		pvt->owner = ch;
 		
-		/* Update usage counter */
-		ast_mutex_lock(&usecnt_lock);
-		usecnt++;
-		ast_mutex_unlock(&usecnt_lock);
-		ast_update_use_count();
-
 		strncpy(ch->context, pvt->context, sizeof(ch->context) - 1);
 		strncpy(ch->exten, pvt->exten, sizeof(ch->exten) - 1);		
 		ch->priority = 1;
@@ -758,6 +803,7 @@
 	} else  {
 		ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
 	}
+	ast_mutex_unlock(&pvt->lock);
 	return ch;
 }
 
@@ -911,10 +957,8 @@
 			ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->nat);
 			ast_rtp_setnat(pvt->rtp, pvt->nat);
 		}
-		pvt->options.noFastStart = p->noFastStart;
-		pvt->options.noH245Tunneling = p->noH245Tunneling;
-		pvt->options.noSilenceSuppression = p->noSilenceSuppression;
-		if (pvt->dtmfmode) {
+		memcpy(&pvt->options, &p->options, sizeof(pvt->options));
+		if (p->dtmfmode) {
 			pvt->dtmfmode = p->dtmfmode;
 			if (pvt->dtmfmode & H323_DTMF_RFC2833) {
 				pvt->nonCodecCapability |= AST_RTP_DTMF;
@@ -937,6 +981,7 @@
 		}		
 		hp = ast_gethostbyname(hostn, &ahp);
 		if (hp) {
+			memcpy(&pvt->options, &global_options, sizeof(pvt->options));
 			memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
 			pvt->sa.sin_port = htons(portno);
 			return 0;	
@@ -950,7 +995,7 @@
 		return 0;
 	}
 }
-static struct ast_channel *oh323_request(const char *type, int format, void *data)
+static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause)
 {
 	int oldformat;
 	struct oh323_pvt *pvt;
@@ -1000,6 +1045,7 @@
 			return NULL;
 		}
 	}
+
 	/* pass on our capabilites to the H.323 stack */
 	ast_mutex_lock(&caplock);
 	h323_set_capability(pvt->capability, pvt->dtmfmode);
@@ -1089,6 +1135,8 @@
 	return info;
 }
 
+int progress(unsigned call_reference, const char *token, int inband);
+
 /**
   * Call-back function passing remote ip/port information from H.323 to asterisk 
   *
@@ -1110,6 +1158,10 @@
 	them.sin_addr.s_addr = inet_addr(remoteIp); 
 	them.sin_port = htons(remotePort);
 	ast_rtp_set_peer(pvt->rtp, &them);
+
+	if (pvt->options.progress_audio) {
+		progress(call_reference, token, 1);
+	}
 	return;
 }
 
@@ -1139,16 +1191,38 @@
 	return;
 }
 
+int progress(unsigned call_reference, const char *token, int inband)
+{
+	struct oh323_pvt *p;
+
+	ast_log(LOG_DEBUG, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
+	p = find_call(call_reference, token);
+
+	if (!p) {
+		ast_log(LOG_ERROR, "Private structure not found in progress.\n");
+		return -1;
+	}
+	if (!p->owner) {
+		ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");
+		return -1;
+	}
+
+	ast_queue_control(p->owner, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));
+
+	return 0;
+}
+
 /**
  *  Call-back function for incoming calls
  *
  *  Returns 1 on success
  */
-int setup_incoming_call(call_details_t cd)
+call_options_t *setup_incoming_call(call_details_t cd)
 {
 	struct oh323_pvt *pvt = NULL;
 	struct oh323_user *user = NULL;
 	struct oh323_alias *alias = NULL;
+	call_options_t *call_options = NULL;
 	char iabuf[INET_ADDRSTRLEN];
 
 	/* allocate the call*/
@@ -1156,7 +1230,7 @@
 
 	if (!pvt) {
 		ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
-		return 0;
+		return NULL;
 	}
 
 	/* Populate the call details in the private structure */
@@ -1185,7 +1259,7 @@
 			alias = find_alias(cd.call_dest_alias);
 			if (!alias) {
 				ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd.call_dest_alias);
-				return 0;
+				return NULL;
 			}
 			strncpy(pvt->exten, alias->name, sizeof(pvt->exten) - 1);
 			strncpy(pvt->context, alias->context, sizeof(pvt->context) - 1);
@@ -1202,17 +1276,18 @@
 			}
 			if (ast_strlen_zero(default_context)) {
 				ast_log(LOG_ERROR, "Call from '%s' rejected due to no default context\n", pvt->cd.call_source_aliases);
-				return 0;
+				return NULL;
 			}
 			strncpy(pvt->context, default_context, sizeof(pvt->context) - 1);
 			ast_log(LOG_DEBUG, "Sending %s to context [%s]\n", cd.call_source_aliases, pvt->context);
+			memset(&pvt->options, 0, sizeof(pvt->options));
 		} else {					
 			if (user->host) {
 				if (strcasecmp(cd.sourceIp, ast_inet_ntoa(iabuf, sizeof(iabuf), user->addr.sin_addr))){					
 					if (ast_strlen_zero(user->context)) {
 						if (ast_strlen_zero(default_context)) {					
 							ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd.sourceIp);
-                					return 0;
+                					return NULL;
 						}
 						strncpy(pvt->context, default_context, sizeof(pvt->context) - 1);
 					} else {
@@ -1238,10 +1313,11 @@
 			if (user->amaflags) {
 				pvt->amaflags = user->amaflags;
 			} 
+			call_options = &user->options;
 		} 
 	}
 exit:
-	return 1;
+	return call_options;
 }
 
 /**
@@ -1357,6 +1433,21 @@
 	return;	
 }
 
+void set_dtmf_payload(unsigned call_reference, const char *token, int payload)
+{
+	struct oh323_pvt *pvt = NULL;
+
+	pvt = find_call(call_reference, token);
+	if (!pvt) {
+		return;
+	}
+	ast_mutex_lock(&pvt->lock);
+	if (pvt->rtp) {
+		ast_rtp_set_rtpmap_type(pvt->rtp, payload, "audio", "telephone-event");
+	}
+	ast_mutex_unlock(&pvt->lock);
+}
+
 static void *do_monitor(void *data)
 {
 	int res;
@@ -1599,6 +1690,8 @@
 	h323debug = 0;
 	dtmfmode = H323_DTMF_RFC2833;
 	memset(&bindaddr, 0, sizeof(bindaddr));
+	memset(&global_options, 0, sizeof(global_options));
+	global_options.dtmfcodec = 101;
 	v = ast_variable_browse(cfg, "general");
 	while(v) {
 		/* Create the interface list */
@@ -1667,14 +1760,18 @@
 				ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
 				dtmfmode = H323_DTMF_RFC2833;
 			}
+		} else if (!strcasecmp(v->name, "dtmfcodec")) {
+			global_options.dtmfcodec = atoi(v->value);
 		} else if (!strcasecmp(v->name, "UserByAlias")) {
                         userbyalias = ast_true(v->value);
                 } else if (!strcasecmp(v->name, "bridge")) {
                         bridging = ast_true(v->value);
                 } else if (!strcasecmp(v->name, "noFastStart")) {
-                        noFastStart = ast_true(v->value);
+                        global_options.noFastStart = ast_true(v->value);
                 } else if (!strcasecmp(v->name, "noH245Tunneling")) {
-                        noH245Tunneling = ast_true(v->value);
+                        global_options.noH245Tunneling = ast_true(v->value);
+		} else if (!strcasecmp(v->name, "noSilenceSuppression")) {
+			global_options.noSilenceSuppression = ast_true(v->value);
 		}
 		v = v->next;	
 	}
@@ -1948,7 +2045,9 @@
 				       chan_ringing,
 				       connection_made, 
 				       send_digit,
-				       answer_call);
+				       answer_call,
+				       progress,
+				       set_dtmf_payload);
 		/* start the h.323 listener */
 		if (h323_start_listener(h323_signalling_port, bindaddr)) {
 			ast_log(LOG_ERROR, "Unable to create H323 listener.\n");




More information about the svn-commits mailing list