diff --git a/channels/chan_h323.c b/channels/chan_h323.c
index 5b92834c58289e1614ecc330b916316e4ffd0be6..a3a22e8c7acc46d62480041c14518332740453dd 100755
--- a/channels/chan_h323.c
+++ b/channels/chan_h323.c
@@ -81,6 +81,8 @@ chan_ringing_cb	on_chan_ringing;
 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 *desc = "The NuFone Network's Open H.323 Channel Driver";
 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_disable = 1;
 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 tos = 0;
 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 @@ static struct oh323_user *build_user(char *name, struct ast_variable *v)
 	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 @@ static struct oh323_user *build_user(char *name, struct ast_variable *v)
                       } 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 @@ static struct oh323_peer *build_peer(char *name, struct ast_variable *v)
 		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 @@ static struct oh323_peer *build_peer(char *name, struct ast_variable *v)
 			} 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 struct oh323_peer *build_peer(char *name, struct ast_variable *v)
  */
 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 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
         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 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
         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 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
 	} 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 @@ static int oh323_hangup(struct ast_channel *c)
 
 	/* 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 @@ static int oh323_indicate(struct ast_channel *c, int condition)
 {
 
 	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 @@ static int oh323_indicate(struct ast_channel *c, int condition)
 		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 @@ static struct ast_channel *oh323_new(struct oh323_pvt *pvt, int state, const cha
 	/* 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 @@ static struct ast_channel *oh323_new(struct oh323_pvt *pvt, int state, const cha
 		/*  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 @@ static struct ast_channel *oh323_new(struct oh323_pvt *pvt, int state, const cha
 	} else  {
 		ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
 	}
+	ast_mutex_unlock(&pvt->lock);
 	return ch;
 }
 
@@ -911,10 +957,8 @@ static int create_addr(struct oh323_pvt *pvt, char *opeer)
 			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 @@ static int create_addr(struct oh323_pvt *pvt, char *opeer)
 		}		
 		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 @@ static int create_addr(struct oh323_pvt *pvt, char *opeer)
 		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 @@ static struct ast_channel *oh323_request(const char *type, int format, void *dat
 			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 @@ struct rtp_info *external_rtp_create(unsigned call_reference, const char * token
 	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 @@ void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int rem
 	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 @@ void connection_made(unsigned call_reference, const char *token)
 	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 @@ int setup_incoming_call(call_details_t cd)
 
 	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 @@ int setup_incoming_call(call_details_t cd)
 			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 @@ int setup_incoming_call(call_details_t cd)
 			}
 			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 @@ int setup_incoming_call(call_details_t cd)
 			if (user->amaflags) {
 				pvt->amaflags = user->amaflags;
 			} 
+			call_options = &user->options;
 		} 
 	}
 exit:
-	return 1;
+	return call_options;
 }
 
 /**
@@ -1357,6 +1433,21 @@ void cleanup_connection(call_details_t cd)
 	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 @@ int reload_config(void)
 	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 @@ int reload_config(void)
 				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 @@ int load_module()
 				       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");
diff --git a/channels/h323/ast_h323.cpp b/channels/h323/ast_h323.cpp
index 6abfff93245b7b8fe80328c85e28c81e0fcfeb68..616b7381b65b57f4c829402527cd3afbb2879d17 100755
--- a/channels/h323/ast_h323.cpp
+++ b/channels/h323/ast_h323.cpp
@@ -156,7 +156,7 @@ H323Codec * H323_G7231Capability::CreateCodec(H323Codec::Direction direction) co
 }
 
 AST_G729Capability::AST_G729Capability()
-  : H323AudioCapability(24, 6)
+  : H323AudioCapability(24, 2)
 {
 }
 
@@ -213,7 +213,7 @@ H323Codec * AST_G729ACapability::CreateCodec(H323Codec::Direction direction) con
   *					transport = ip.
   *					port = 1720.
   */
-int MyH323EndPoint::MakeCall(const PString & dest, PString & token, unsigned int *callReference, char *cid_name, char *cid_num)
+int MyH323EndPoint::MakeCall(const PString & dest, PString & token, unsigned int *callReference, call_options_t *opts)
 {
 	PString fullAddress;
 	MyH323Connection * connection;
@@ -237,20 +237,23 @@ int MyH323EndPoint::MakeCall(const PString & dest, PString & token, unsigned int
 		return 1;
 	}
 	*callReference = connection->GetCallReference();	
-	if (cid_name) {
+	if (opts->cid_name) {
                 localAliasNames.RemoveAll();
-		connection->SetLocalPartyName(PString(cid_name));
-	        if (cid_num) {
-                	localAliasNames.AppendString(PString(cid_num));
+		connection->SetLocalPartyName(PString(opts->cid_name));
+	        if (opts->cid_num) {
+                	localAliasNames.AppendString(PString(opts->cid_num));
 		}
-        } else if (cid_num) {
+        } else if (opts->cid_num) {
                 localAliasNames.RemoveAll();
-                connection->SetLocalPartyName(PString(cid_num));
+                connection->SetLocalPartyName(PString(opts->cid_num));
         }
+	connection->dtmfCodec = (RTP_DataFrame::PayloadTypes)opts->dtmfcodec;
+
 	if (h323debug) {
 		cout << "\t-- " << GetLocalUserName() << " is calling host " << fullAddress << endl;
 		cout << "\t--" << "Call token is " << (const char *)token << endl;
 		cout << "\t-- Call reference is " << *callReference << endl;
+		cout << "\t-- DTMF Payload is " << connection->dtmfCodec << endl;
 	}
 	connection->Unlock(); 	
 	return 0;
@@ -259,6 +262,12 @@ int MyH323EndPoint::MakeCall(const PString & dest, PString & token, unsigned int
 void MyH323EndPoint::SetEndpointTypeInfo( H225_EndpointType & info ) const
 {
   	H323EndPoint::SetEndpointTypeInfo(info);
+
+	if (terminalType == e_GatewayOnly){
+		info.RemoveOptionalField(H225_EndpointType::e_terminal);
+		info.IncludeOptionalField(H225_EndpointType::e_gateway);
+	}
+
   	info.m_gateway.IncludeOptionalField(H225_GatewayInfo::e_protocol);
   	info.m_gateway.m_protocol.SetSize(1);
   	H225_SupportedProtocols &protocol=info.m_gateway.m_protocol[0];
@@ -280,12 +289,20 @@ H323Capabilities MyH323EndPoint::GetCapabilities(void)
 	return capabilities;
 }
 
+BOOL MyH323EndPoint::ClearCall(const PString & token, H323Connection::CallEndReason reason)
+{
+	if (h323debug) {
+		cout << "\t-- ClearCall: Request to clear call with token " << token << ", cause " << reason << endl;
+	}
+	return H323EndPoint::ClearCall(token, reason);
+}
+
 BOOL MyH323EndPoint::ClearCall(const PString & token)
 {
 	if (h323debug) {
 		cout << "\t-- ClearCall: Request to clear call with token " << token << endl;
 	}
-	return H323EndPoint::ClearCall(token);
+	return ClearCall(token, H323Connection::EndedByLocalUser);
 }
 
 void MyH323EndPoint::SendUserTone(const PString &token, char tone)
@@ -506,29 +523,99 @@ MyH323Connection::~MyH323Connection()
 	return;
 }
 
+BOOL MyH323Connection::OnReceivedProgress(const H323SignalPDU &pdu)
+{
+	BOOL isInband;
+	unsigned pi;
+
+	if (!H323Connection::OnReceivedProgress(pdu)) {
+		return FALSE;
+	}
+
+	if (!pdu.GetQ931().GetProgressIndicator(pi))
+		pi = 0;
+	if (h323debug) {
+		cout << "\t- Progress Indicator: " << pi << endl;
+	}
+	
+	switch(pi) {
+	case Q931::ProgressNotEndToEndISDN:
+	case Q931::ProgressInbandInformationAvailable:
+		isInband = TRUE;
+		break;
+	default:
+		isInband = FALSE;
+	}
+	on_progress(GetCallReference(), (const char *)GetCallToken(), isInband);
+
+	return TRUE;
+}
+
 H323Connection::AnswerCallResponse MyH323Connection::OnAnswerCall(const PString & caller,
-								  const H323SignalPDU & /*setupPDU*/,
+								  const H323SignalPDU & setupPDU,
 								  H323SignalPDU & /*connectPDU*/)
 {
+	unsigned pi;
 
-       if (h323debug) {
+	if (h323debug) {
                cout << "\t=-= In OnAnswerCall for call " << GetCallReference() << endl;
 	}
+
+	if (!setupPDU.GetQ931().GetProgressIndicator(pi)) {
+		pi = 0;
+	}
+	if (h323debug) {
+		cout << "\t\t- Progress Indicator: " << pi << endl;
+	}
+	if (progressAlert) {
+		pi = progressAlert;
+	} else if (pi == Q931::ProgressOriginNotISDN) {
+		pi = Q931::ProgressInbandInformationAvailable;
+	}
+	if (pi) {
+		alertingPDU->GetQ931().SetProgressIndicator(pi);
+	}
+	if (h323debug) {
+		cout << "\t\t- Inserting PI of " << pi << " into ALERTING message" << endl;
+	}
+
 	if (!on_answer_call(GetCallReference(), (const char *)GetCallToken())) {
 		return H323Connection::AnswerCallDenied;
 	}
 	/* The call will be answered later with "AnsweringCall()" function.
 	 */ 
-	return H323Connection::AnswerCallDeferred;
+	return H323Connection::AnswerCallDeferredWithMedia;
 }
 
-BOOL MyH323Connection::OnAlerting(const H323SignalPDU & /*alertingPDU*/, const PString & username)
+BOOL MyH323Connection::OnAlerting(const H323SignalPDU & alertingPDU, const PString & username)
 {
 	if (h323debug) {
 	        cout << "\t=-= In OnAlerting for call " << GetCallReference()
 	              << ": sessionId=" << sessionId << endl;
                  cout << "\t-- Ringing phone for \"" << username << "\"" << endl;
-	}     
+	}
+
+	if (on_progress) {
+		BOOL isInband;
+		unsigned alertingPI;
+
+		if (!alertingPDU.GetQ931().GetProgressIndicator(alertingPI)) {
+			alertingPI = 0;
+		}
+		if (h323debug) {
+			cout << "\t\t- Progress Indicator: " << alertingPI << endl;
+		}
+		
+		switch(alertingPI) {
+		case Q931::ProgressNotEndToEndISDN:
+		case Q931::ProgressInbandInformationAvailable:
+			isInband = TRUE;
+			break;
+		default:
+			isInband = FALSE;
+		}
+		on_progress(GetCallReference(), (const char *)GetCallToken(), isInband);
+	}
         on_chan_ringing(GetCallReference(), (const char *)GetCallToken() );
         return TRUE;
 }
@@ -588,7 +675,7 @@ BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
  	cd.sourceIp = strdup((const char *)Ip.AsString());
 
 	/* Notify Asterisk of the request */
-	int res = on_incoming_call(cd); 
+	call_options_t *res = on_incoming_call(cd); 
 
 	if (!res) {
 		if (h323debug) {
@@ -596,6 +683,12 @@ BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
 		}
 		return FALSE;
 	}
+
+	progressSetup = res->progress_setup;
+	progressAlert = res->progress_alert;
+	dtmfCodec = (RTP_DataFrame::PayloadTypes)res->dtmfcodec;
+
+
 	return H323Connection::OnReceivedSignalSetup(setupPDU);
 }
 
@@ -646,6 +739,10 @@ BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
 		}
 		return FALSE;
 	}
+
+	if (progressSetup) {
+		setupPDU.GetQ931().SetProgressIndicator(progressSetup);
+	}
 	return H323Connection::OnSendSignalSetup(setupPDU);
 }
 
@@ -711,6 +808,50 @@ void MyH323Connection::OnUserInputString(const PString &value)
 	}	
 }
 
+void MyH323Connection::OnSendCapabilitySet(H245_TerminalCapabilitySet & pdu)
+{
+	PINDEX i;
+
+	H323Connection::OnSendCapabilitySet(pdu);
+
+	H245_ArrayOf_CapabilityTableEntry & tables = pdu.m_capabilityTable;
+	for(i = 0; i < tables.GetSize(); i++)
+	{
+		H245_CapabilityTableEntry & entry = tables[i];
+		if (entry.HasOptionalField(H245_CapabilityTableEntry::e_capability)) {
+			H245_Capability & cap = entry.m_capability;
+			if (cap.GetTag() == H245_Capability::e_receiveRTPAudioTelephonyEventCapability) {
+				H245_AudioTelephonyEventCapability & atec = cap;
+				atec.m_dynamicRTPPayloadType = dtmfCodec;
+				on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)dtmfCodec);
+				if (h323debug) {
+					cout << "\t-- Transmitting RFC2833 on payload " <<
+						atec.m_dynamicRTPPayloadType << endl;
+				}
+			}
+		}
+	}
+}
+
+BOOL MyH323Connection::OnReceivedCapabilitySet(const H323Capabilities & remoteCaps,
+					       const H245_MultiplexCapability * muxCap,
+					       H245_TerminalCapabilitySetReject & reject)
+{
+	if (!H323Connection::OnReceivedCapabilitySet(remoteCaps, muxCap, reject)) {
+		return FALSE;
+	}
+
+	const H323Capability * cap = remoteCaps.FindCapability(H323_UserInputCapability::SubTypeNames[H323_UserInputCapability::SignalToneRFC2833]);
+	if (cap != NULL) {
+		RTP_DataFrame::PayloadTypes pt = ((H323_UserInputCapability*)cap)->GetPayloadType();
+		on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)pt);
+		if (h323debug) {
+			cout << "\t-- Inbound RFC2833 on payload " << pt << endl;
+		}
+	}
+	return TRUE;
+}
+
 H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability,	
 								   H323Channel::Directions dir,
 								   unsigned sessionID,
@@ -783,7 +924,7 @@ BOOL MyH323_ExternalRTPChannel::Start(void)
 	}
 
 	/* Collect the remote information */
-	GetRemoteAddress(remoteIpAddr, remotePort);
+	H323_ExternalRTPChannel::GetRemoteAddress(remoteIpAddr, remotePort);
 
         if (h323debug) {
         	cout << "\t\tExternal RTP Session Starting" << endl;
@@ -800,6 +941,28 @@ BOOL MyH323_ExternalRTPChannel::Start(void)
 	return TRUE;
 }
 
+BOOL MyH323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
+{
+	PIPSocket::Address remoteIpAddress;
+	WORD remotePort;
+
+	if (h323debug) {
+		cout << "	MyH323_ExternalRTPChannel::OnReceivedAckPDU" << endl;
+	}
+
+	if (H323_ExternalRTPChannel::OnReceivedAckPDU(param)) {
+		GetRemoteAddress(remoteIpAddress, remotePort);
+		if (h323debug) {
+			cout << "		-- remoteIpAddress: " << remoteIpAddress << endl;
+			cout << "		-- remotePort: " << remotePort << endl;
+		}
+		on_start_rtp_channel(connection.GetCallReference(), (const char *)remoteIpAddress.AsString(),
+				remotePort, (const char *)connection.GetCallToken());
+		return TRUE;
+	}
+	return FALSE;
+}
+
 /** IMPLEMENTATION OF C FUNCTIONS */
 
 /**
@@ -859,7 +1022,9 @@ void h323_callback_register(setup_incoming_cb  	ifunc,
  			    chan_ringing_cb     rfunc,
 			    con_established_cb 	efunc,
  			    send_digit_cb	dfunc,
- 			    answer_call_cb	acfunc)
+ 			    answer_call_cb	acfunc,
+			    progress_cb		pgfunc,
+			    rfc2833_cb		dtmffunc)
 {
 	on_incoming_call = ifunc;
 	on_outgoing_call = sfunc;
@@ -870,6 +1035,8 @@ void h323_callback_register(setup_incoming_cb  	ifunc,
 	on_connection_established = efunc;
 	on_send_digit = dfunc;
 	on_answer_call = acfunc;
+	on_progress = pgfunc;
+	on_set_rfc2833_payload = dtmffunc;
 }
 
 /**
@@ -879,8 +1046,9 @@ int h323_set_capability(int cap, int dtmfMode)
 {
 	H323Capabilities oldcaps;
 	PStringArray codecs;
-	int g711Frames = 30;
+	int g711Frames = 20;
 //	int gsmFrames  = 4;
+	PINDEX lastcap = -1; /* last common capability index */
 
 	if (!h323_end_point_exist()) {
 		cout << " ERROR: [h323_set_capablity] No Endpoint, this is bad" << endl;
@@ -894,12 +1062,6 @@ int h323_set_capability(int cap, int dtmfMode)
         }
         endPoint->RemoveCapabilities(codecs);
 
-	mode = dtmfMode;
-	if (dtmfMode == H323_DTMF_INBAND) {
-	    endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
-	} else {
-		endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
-	}
 #if 0
 	if (cap & AST_FORMAT_SPEEX) {
 		/* Not real sure if Asterisk acutally supports all
@@ -916,32 +1078,45 @@ int h323_set_capability(int cap, int dtmfMode)
 	if (cap & AST_FORMAT_G729A) {
 		AST_G729ACapability *g729aCap;
 		AST_G729Capability *g729Cap;
-		endPoint->SetCapability(0, 0, g729aCap = new AST_G729ACapability);
-		endPoint->SetCapability(0, 0, g729Cap = new AST_G729Capability);
+		lastcap = endPoint->SetCapability(0, 0, g729aCap = new AST_G729ACapability);
+		lastcap = endPoint->SetCapability(0, 0, g729Cap = new AST_G729Capability);
 	}
 	
 	if (cap & AST_FORMAT_G723_1) {
 		H323_G7231Capability *g7231Cap;
-		endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
+		lastcap = endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
 	} 
 #if 0
 	if (cap & AST_FORMAT_GSM) {
 		H323_GSM0610Capability *gsmCap;
-	    	endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
+	    	lastcap = endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
 	    	gsmCap->SetTxFramesInPacket(gsmFrames);
 	} 
 #endif
 	if (cap & AST_FORMAT_ULAW) {
 		H323_G711Capability *g711uCap;
-	    	endPoint->SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
+	    	lastcap = endPoint->SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
 		g711uCap->SetTxFramesInPacket(g711Frames);
 	} 
 
 	if (cap & AST_FORMAT_ALAW) {
 		H323_G711Capability *g711aCap;
-		endPoint->SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
+		lastcap = endPoint->SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
 		g711aCap->SetTxFramesInPacket(g711Frames);
-	} 
+	}
+
+	lastcap++;
+	lastcap = endPoint->SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::HookFlashH245));
+
+	lastcap++;
+	mode = dtmfMode;
+	if (dtmfMode == H323_DTMF_INBAND) {
+		endPoint->SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245));
+		endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
+	} else {
+		endPoint->SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneRFC2833));
+		endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
+	}
 
 	if (h323debug) {
 		cout <<  "Allowed Codecs:\n\t" << setprecision(2) << endPoint->GetCapabilities() << endl;
@@ -1086,7 +1261,7 @@ void h323_send_tone(const char *call_token, char tone)
 
 /** Make a call to the remote endpoint.
   */
-int h323_make_call(char *dest, call_details_t *cd, call_options_t call_options)
+int h323_make_call(char *dest, call_details_t *cd, call_options_t *call_options)
 {
 	int res;
 	PString	token;
@@ -1096,17 +1271,23 @@ int h323_make_call(char *dest, call_details_t *cd, call_options_t call_options)
 		return 1;
 	}
 
-	res = endPoint->MakeCall(host, token, &cd->call_reference, call_options.cid_name, call_options.cid_num);
+	res = endPoint->MakeCall(host, token, &cd->call_reference, call_options);
 	memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
 	return res;
 };
 
-int h323_clear_call(const char *call_token)
+int h323_clear_call(const char *call_token, int cause)
 {
+	H225_ReleaseCompleteReason dummy;
+	H323Connection::CallEndReason r = H323Connection::NumCallEndReasons;
+
 	if (!h323_end_point_exist()) {
 		return 1;
 	}
-        endPoint->ClearCall(PString(call_token));
+
+	r = H323TranslateToCallEndReason((Q931::CauseValues)(cause), dummy);
+
+        endPoint->ClearCall(PString(call_token), r);
 	return 0;
 };
 
@@ -1184,7 +1365,7 @@ int h323_soft_hangup(const char *data)
 {
 	PString token(data);
 	BOOL result;
-	
+	cout << "Soft hangup" << endl;	
 	result = endPoint->ClearCall(token);	
 	return result;
 }
diff --git a/channels/h323/ast_h323.h b/channels/h323/ast_h323.h
index f9a454b6f5cb65e3d4b84f38b79c79337899190e..906acd65d12487752ab68805c43efb3dce04a74e 100755
--- a/channels/h323/ast_h323.h
+++ b/channels/h323/ast_h323.h
@@ -128,7 +128,8 @@ class MyH323EndPoint : public H323EndPoint {
 	PCLASSINFO(MyH323EndPoint, H323EndPoint);
 
 	public:
-	int MakeCall(const PString &, PString &, unsigned int *, char *, char *);
+	int MakeCall(const PString &, PString &, unsigned int *, call_options_t *opts);
+	BOOL ClearCall(const PString &, H323Connection::CallEndReason reason);
 	BOOL ClearCall(const PString &);
 
 	void OnClosedLogicalChannel(H323Connection &, const H323Channel &);
@@ -170,6 +171,10 @@ class MyH323Connection : public H323Connection {
 	void SendUserInputTone(char, unsigned);
 	void OnUserInputTone(char, unsigned, unsigned, unsigned);
 	void OnUserInputString(const PString &value);
+	BOOL OnReceivedProgress(const H323SignalPDU &);
+	void OnSendCapabilitySet(H245_TerminalCapabilitySet &);
+	BOOL OnReceivedCapabilitySet(const H323Capabilities &, const H245_MultiplexCapability *,
+				     H245_TerminalCapabilitySetReject &);
 
 	PString sourceAliases;
 	PString destAliases;
@@ -178,6 +183,11 @@ class MyH323Connection : public H323Connection {
 
 	WORD sessionId;
 	BOOL bridging;			
+
+	unsigned progressSetup;
+	unsigned progressAlert;
+
+	RTP_DataFrame::PayloadTypes dtmfCodec;
 };
 
 class MyH323_ExternalRTPChannel : public H323_ExternalRTPChannel {
@@ -192,9 +202,10 @@ class MyH323_ExternalRTPChannel : public H323_ExternalRTPChannel {
       		unsigned sessionID);
 
 	~MyH323_ExternalRTPChannel();
-	
+
 	/* Overrides */
 	BOOL Start(void);
+	BOOL OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param);
 
 	protected:
 	BYTE payloadCode;
diff --git a/channels/h323/chan_h323.h b/channels/h323/chan_h323.h
index 0005b421ce6742e976a04b81a3c73e65a5539649..995b81896deb99564f0a0347a172e43ccee658c9 100755
--- a/channels/h323/chan_h323.h
+++ b/channels/h323/chan_h323.h
@@ -28,7 +28,20 @@
 
 #include <arpa/inet.h>
 
-static struct sockaddr_in bindaddr;
+/** call_option struct holds various bits
+ *         of information for each call */
+typedef struct call_options {
+	char            *cid_num;
+	char            *cid_name;
+	int             noFastStart;
+	int             noH245Tunneling;
+	int             noSilenceSuppression;
+	unsigned int    port;
+	int             progress_setup;
+	int             progress_alert;
+	int             progress_audio;
+	int		dtmfcodec;
+} call_options_t;
 
 /* structure to hold the valid asterisk users */
 struct oh323_user {
@@ -38,13 +51,11 @@ struct oh323_user {
 	char callerid[80];
 	char accountcode[20];
 	int amaflags;
-	int noFastStart;
-	int noH245Tunneling;
-	int noSilenceSuppression;
 	int bridge;
 	int nat;
 	int dtmfmode;
 	int host;
+	call_options_t options;
 	struct ast_ha *ha;
 	struct sockaddr_in addr;
 	struct oh323_user *next;
@@ -56,15 +67,13 @@ struct oh323_peer {
 	char name[80];
 	char mailbox[80];
 	int capability;
-	int noFastStart;
-	int noH245Tunneling;
-	int noSilenceSuppression;
 	int bridge;
 	int nat;
 	int dtmfmode;
 	int delme;
 	struct sockaddr_in addr;
 	struct ast_ha *ha;
+	call_options_t options;
 	struct oh323_peer *next;
 };
 
@@ -79,17 +88,6 @@ struct oh323_alias {
 	struct oh323_alias *next;	
 };
 
-/** call_option struct holds various bits 
-	of information for each call */
-typedef struct call_options {
-	char		*cid_num;
-	char		*cid_name;
-	int	  	noFastStart;
-	int		noH245Tunneling;
-	int		noSilenceSuppression;
-	unsigned int	port;
-} call_options_t;
-
 /** call_details struct call detail records 
 	to asterisk for processing and used for matching up 
 	asterisk channels to acutal h.323 connections */
@@ -124,9 +122,14 @@ extern on_rtp_cb on_external_rtp_create;
 typedef void (*start_rtp_cb)(unsigned int, const char *, int, const char *);
 extern start_rtp_cb on_start_rtp_channel; 
 
+/* This is a callback that happens when call progress is
+ * made, and handles inband progress */
+typedef int (*progress_cb)(unsigned, const char *, int);
+extern progress_cb on_progress;
+
 /* This is a callback prototype function, called upon
    an incoming call happens. */
-typedef int (*setup_incoming_cb)(call_details_t);
+typedef call_options_t *(*setup_incoming_cb)(call_details_t);
 extern setup_incoming_cb on_incoming_call;
 
 /* This is a callback prototype function, called upon
@@ -154,12 +157,22 @@ extern clear_con_cb on_connection_cleared;
 typedef int (*answer_call_cb)(unsigned, const char *);
 extern answer_call_cb on_answer_call;
 
+/* This is a callback prototype function, called when
+   we know which RTP payload type RFC2833 will be
+   transmitted */
+typedef void (*rfc2833_cb)(unsigned, const char *, int);
+extern rfc2833_cb on_set_rfc2833_payload;
+
 /* debug flag */
 extern int h323debug;
 
 #define H323_DTMF_RFC2833	(1 << 0)
 #define H323_DTMF_INBAND	(1 << 1)
 
+#ifndef BOOL
+#define BOOL int
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif   
@@ -180,7 +193,9 @@ extern "C" {
  				    chan_ringing_cb,
 				    con_established_cb,
  				    send_digit_cb,
- 				    answer_call_cb);
+ 				    answer_call_cb,
+				    progress_cb,
+				    rfc2833_cb);
 	int h323_set_capability(int, int);
 	int h323_set_alias(struct oh323_alias *);
 	int h323_set_gk(int, char *, char *);
@@ -196,8 +211,8 @@ extern "C" {
 	void h323_send_tone(const char *call_token, char tone);
 
 	/* H323 create and destroy sessions */
-	int h323_make_call(char *dest, call_details_t *cd, call_options_t);
-	int h323_clear_call(const char *);
+	int h323_make_call(char *dest, call_details_t *cd, call_options_t *);
+	int h323_clear_call(const char *, int cause);
 	
 	/* H.323 alerting and progress */
 	int h323_send_alerting(const char *token);