[svn-commits] may: branch may/chan_ooh323_rework r207350 - in /team/may/chan_ooh323_rework/...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Sat Jul 18 21:50:16 CDT 2009


Author: may
Date: Sat Jul 18 21:50:11 2009
New Revision: 207350

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=207350
Log:
initial t.38 support in transparent audio->t38 mode
now accept request mode, sent req mode ack and work with t38

Modified:
    team/may/chan_ooh323_rework/addons/chan_ooh323.c
    team/may/chan_ooh323_rework/addons/chan_ooh323.h
    team/may/chan_ooh323_rework/addons/ooh323c/src/ooCalls.c
    team/may/chan_ooh323_rework/addons/ooh323c/src/ooCalls.h
    team/may/chan_ooh323_rework/addons/ooh323c/src/ooCapability.c
    team/may/chan_ooh323_rework/addons/ooh323c/src/ooCapability.h
    team/may/chan_ooh323_rework/addons/ooh323c/src/ooh245.c
    team/may/chan_ooh323_rework/addons/ooh323c/src/ooh323ep.c
    team/may/chan_ooh323_rework/addons/ooh323c/src/ooq931.c
    team/may/chan_ooh323_rework/addons/ooh323c/src/ootypes.h
    team/may/chan_ooh323_rework/addons/ooh323cDriver.c

Modified: team/may/chan_ooh323_rework/addons/chan_ooh323.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/may/chan_ooh323_rework/addons/chan_ooh323.c?view=diff&rev=207350&r1=207349&r2=207350
==============================================================================
--- team/may/chan_ooh323_rework/addons/chan_ooh323.c (original)
+++ team/may/chan_ooh323_rework/addons/chan_ooh323.c Sat Jul 18 21:50:11 2009
@@ -16,6 +16,8 @@
 
 
 #include "chan_ooh323.h"
+#include <math.h>
+#include <spandsp.h>
 
 /* Defaults */
 #define DEFAULT_CONTEXT "default"
@@ -57,6 +59,9 @@
 static enum ast_rtp_glue_result ooh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp);
 static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, 
           struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, int codecs, int nat_active);
+
+static struct ast_udptl *ooh323_get_udptl_peer(struct ast_channel *chan);
+static int ooh323_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl);
 
 static void print_codec_to_cli(int fd, struct ast_codec_pref *pref);
 static void ast_ooh323c_exit();
@@ -88,6 +93,14 @@
 	.update_peer = ooh323_set_rtp_peer,
 };
 
+static struct ast_udptl_protocol ooh323_udptl = {
+	type: "H323",
+	get_udptl_info: ooh323_get_udptl_peer,
+	set_udptl_peer: ooh323_set_udptl_peer,
+};
+
+
+
 struct ooh323_user;
 
 /* H.323 channel private structure */
@@ -95,6 +108,15 @@
 	ast_mutex_t lock;		/* Channel private lock */
 	struct ast_rtp_instance *rtp;
 	struct ast_rtp_instance *vrtp; /* Placeholder for now */
+
+	struct ast_udptl *udptl;
+	int faxmode;
+	int t38_tx_enable;
+	int t38_init;
+	t38_gateway_state_t t38r_state;
+	struct sockaddr_in udptlredirip;
+	time_t lastTxT38;
+
 	struct ast_channel *owner;	/* Master Channel */
    	union {
     		char  *user;	/* cooperating user/peer */
@@ -209,6 +231,7 @@
 int onOutgoingCall(ooCallData *call);
 int onCallEstablished(ooCallData *call);
 int onCallCleared(ooCallData *call);
+void onModeChanged(ooCallData *call, int t38mode);
 
 static char gLogFile[256] = DEFAULT_LOGFILE;
 static int  gPort = 1720;
@@ -294,6 +317,7 @@
 
 		ast_channel_set_fd(ch, 0, ast_rtp_instance_fd(i->rtp, 0));
 		ast_channel_set_fd(ch, 1, ast_rtp_instance_fd(i->rtp, 1));
+		ast_channel_set_fd(ch, 5, ast_udptl_fd(i->udptl));
 
 		if (state == AST_STATE_RING)
 			ch->rings = 1;
@@ -413,6 +437,18 @@
 	}
  
 	ast_rtp_instance_set_qos(pvt->rtp, gTOS, 0, "ooh323-rtp");
+
+	if (!(pvt->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, ipAddr))) {
+		ast_log(LOG_WARNING, "Unable to create UDPTL session: %s\n",
+				strerror(errno));
+		ast_mutex_unlock(&pvt->lock);
+		ast_mutex_destroy(&pvt->lock);
+		free(pvt);
+		return NULL;
+	}
+
+	ast_udptl_set_error_correction_scheme(pvt->udptl, UDPTL_ERROR_CORRECTION_NONE);
+	pvt->faxmode = 0;
 
 	pvt->call_reference = callref;
 	if (callToken)
@@ -979,18 +1015,65 @@
 	struct ooh323_pvt *p = ast->tech_pvt;
 	int res = 0;
 	char *callToken = (char *)NULL;
+	int16_t* t38data;
+	int t38samples;
 
 	if (p) {
 		ast_mutex_lock(&p->lock);
+
+		if (f->frametype == AST_FRAME_MODEM) {
+			ast_debug(1, "Send UDPTL %d/%d len %d for %s\n",
+				f->frametype, f->subclass, f->datalen, ast->name);
+			if (p->udptl)
+				res = ast_udptl_write(p->udptl, f);
+			ast_mutex_unlock(&p->lock);
+			return res;
+		}
+
 	
+		if (f->frametype == AST_FRAME_VOICE) {
 /* sending progress for first */
-		if (!ast_test_flag(p, H323_OUTGOING) && !p->progsent) {
-			callToken = (p->callToken ? strdup(p->callToken) : NULL);
-			ooManualProgress(callToken);
-			p->progsent = 1;
-			free(callToken);
-		}
-		if (f->frametype == AST_FRAME_VOICE) {
+			if (!ast_test_flag(p, H323_OUTGOING) && !p->progsent) {
+				callToken = (p->callToken ? strdup(p->callToken) : NULL);
+				ooManualProgress(callToken);
+				p->progsent = 1;
+				free(callToken);
+			}
+
+
+/* if we are in fax t30-t38 transparent mode */
+
+			if (p->faxmode) {
+				if (f->subclass == AST_FORMAT_SLINEAR) {
+                        		t38data = f->data.ptr;
+                        		t38samples = f->samples;
+                 		} else {
+				 	t38samples = 0;
+					ast_verbose("Got non-slin frame for %s in fax mode\n",
+						ast->name);
+					ast_set_write_format(ast, AST_FORMAT_SLINEAR);
+					ast_set_read_format(ast, AST_FORMAT_SLINEAR);
+					ast_mutex_unlock(&p->lock);
+					return 0;
+				}
+
+                 		if (t38samples) {
+                        		t38_gateway_rx(&p->t38r_state, t38data, t38samples);
+					if (gH323Debug)
+						ast_debug(4, "t38gw_rx %d\n", t38samples);
+				}
+                        	res = f->samples;
+                		time_t ct = time(NULL);
+                		/* if (ct - pvt->lastTxT38 > T38TOAUDIOTIMEOUT && !p->chmodepend) {
+                        		ast_debug(1,"request to change %s to audio because t38 timeout\n", ast->name);
+                        		h323_mode_change(token,0);
+                        			pvt->chmodepend = 1;
+                        	} */
+				ast_mutex_unlock(&p->lock);
+				return res;
+			}
+
+
 			if (!(f->subclass & ast->nativeformats)) {
 				if (ast->nativeformats != 0) {
 					ast_log(LOG_WARNING, "Asked to transmit frame type %d,"
@@ -2763,7 +2846,8 @@
 		.onCallEstablished = onCallEstablished,
 		.onCallCleared = onCallCleared,
 		.openLogicalChannels = NULL,
-		.onReceivedDTMF = &ooh323_onReceivedDigit
+		.onReceivedDTMF = &ooh323_onReceivedDigit,
+		.onModeChanged = onModeChanged
 	};
 
 	ast_log(LOG_NOTICE, 
@@ -2800,6 +2884,7 @@
 			return 0;
 		}
 		ast_rtp_glue_register(&ooh323_rtp);
+		ast_udptl_proto_register(&ooh323_udptl);
 		ast_cli_register_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry));
 
 		 /* fire up the H.323 Endpoint */		 
@@ -3064,7 +3149,12 @@
 
 		if (cur->rtp) {
 			ast_rtp_instance_destroy(cur->rtp);
-			cur->rtp = 0;
+			cur->rtp = NULL;
+		}
+
+		if (cur->udptl) {
+			ast_udptl_destroy(cur->udptl);
+			cur->udptl = NULL;
 		}
 	
 		/* Unlink us from the owner if we have one */
@@ -3169,6 +3259,7 @@
 	/* First, take us out of the channel loop */
 	ast_cli_unregister_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry));
 	ast_rtp_glue_unregister(&ooh323_rtp);
+	ast_udptl_proto_unregister(&ooh323_udptl);
 	ast_channel_unregister(&ooh323_tech);
 #if 0
 	ast_unregister_atexit(&ast_ooh323c_exit);
@@ -3437,6 +3528,16 @@
 		}
 	}
 
+	ast_udptl_get_us(p->udptl, &us);
+	ast_copy_string(mediaInfo.lMediaIP, ast_inet_ntoa(us.sin_addr), sizeof(mediaInfo.lMediaIP));
+	mediaInfo.lMediaPort = ntohs(us.sin_port);
+	mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort +1;
+	mediaInfo.cap = OO_T38;
+	strcpy(mediaInfo.dir, "transmit");
+	ooAddMediaInfo(call, mediaInfo);
+	strcpy(mediaInfo.dir, "receive");
+	ooAddMediaInfo(call, mediaInfo);
+
 	if (gH323Debug)
 		ast_verbose("+++   configure_local_rtp\n");
 
@@ -3448,7 +3549,6 @@
 {
 	struct ooh323_pvt *p = NULL;
 	struct sockaddr_in them;
-	char *callToken = (char *)NULL;
 
 	if (gH323Debug)
 		ast_verbose("---   setup_rtp_connection\n");
@@ -3501,6 +3601,103 @@
 	return;
 }
 
+/*
+ udptl handling functions
+ */
+
+static struct ast_udptl *ooh323_get_udptl_peer(struct ast_channel *chan)
+{
+	struct ooh323_pvt *p;
+	struct ast_udptl *udptl = NULL;
+
+	p = chan->tech_pvt;
+	if (!p)
+		return NULL;
+
+	ast_mutex_lock(&p->lock);
+	if (p->udptl)
+		udptl = p->udptl;
+	ast_mutex_unlock(&p->lock);
+	return udptl;
+}
+
+static int ooh323_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl)
+{
+	struct ooh323_pvt *p;
+
+	p = chan->tech_pvt;
+	if (!p)
+		return -1;
+	ast_mutex_lock(&p->lock);
+	if (udptl)
+		ast_udptl_get_peer(udptl, &p->udptlredirip);
+	else
+		memset(&p->udptlredirip, 0, sizeof(p->udptlredirip));
+
+	ast_mutex_unlock(&p->lock);
+	return 0;
+}
+
+void setup_udptl_connection(ooCallData *call, const char *remoteIp, 
+								  int remotePort)
+{
+	struct ooh323_pvt *p = NULL;
+	struct sockaddr_in them;
+
+	if (gH323Debug)
+		ast_verbose("---   setup_udptl_connection\n");
+
+	/* Find the call or allocate a private structure if call not found */
+	p = find_call(call); 
+
+	if (!p) {
+		ast_log(LOG_ERROR, "Something is wrong: rtp\n");
+		return;
+	}
+
+	ast_mutex_lock(&p->lock);
+
+	them.sin_family = AF_INET;
+	them.sin_addr.s_addr = inet_addr(remoteIp); /* only works for IPv4 */
+	them.sin_port = htons(remotePort);
+	ast_udptl_set_peer(p->udptl, &them);
+	p->t38_tx_enable = 1;
+	p->lastTxT38 = time(NULL);
+	if (gH323Debug)
+		ast_debug(1, "Receiving UDPTL  %s:%d\n", ast_inet_ntoa(them.sin_addr), 
+							 ntohs(them.sin_port));
+	ast_mutex_unlock(&p->lock);
+
+	if(gH323Debug)
+		ast_verbose("+++   setup_udptl_connection\n");
+
+	return;
+}
+
+void close_udptl_connection(ooCallData *call)
+{
+	struct ooh323_pvt *p = NULL;
+
+   	if(gH323Debug)
+		ast_verbose("---   close_udptl_connection\n");
+
+	p = find_call(call);
+	if (!p) {
+      		ast_log(LOG_ERROR, "Couldn't find matching call to close udptl "
+                         "connection\n");
+		return;
+	}
+	ast_mutex_lock(&p->lock);
+	p->t38_tx_enable = 0;
+	ast_mutex_unlock(&p->lock);
+
+   	if(gH323Debug)
+		ast_verbose("+++   close_udptl_connection\n");
+
+	return;
+}
+
+/* end of udptl handling */
 
 int update_our_aliases(ooCallData *call, struct ooh323_pvt *p)
 {
@@ -3549,6 +3746,19 @@
 	case 3:
 		f = ast_rtp_instance_read(p->vrtp, 1);	/* RTCP Control Channel for video */
 		break;
+	case 5:
+		f = ast_udptl_read(p->udptl);		/* UDPTL t.38 data */
+		if (gH323Debug) ast_debug(1, "Got UDPTL %d/%d len %d for %s\n",
+				f->frametype, f->subclass, f->datalen, ast->name);
+		if (!p->faxmode) p->faxmode = 1;
+		if (p->t38_init) {
+			t38_core_rx_ifp_packet(&p->t38r_state.t38, (uint8_t *)f->data.ptr,
+                                         f->datalen, 0);
+			p->lastTxT38 = time(NULL);
+                }
+                f = &null_frame;
+                break;
+
 	default:
 		f = &null_frame;
 	}
@@ -3580,6 +3790,189 @@
 	}
 	return f;
 }
+
+#define MAXT30  240
+
+static int t30_read(const void *data) {
+
+	struct ast_channel *c = (struct ast_channel *) data;
+	struct ooh323_pvt *p = (struct ooh323_pvt *) c->tech_pvt;
+	int len;
+
+	static uint8_t buffer[AST_FRIENDLY_OFFSET + MAXT30 * sizeof(uint16_t)];
+	int16_t *buf = (int16_t *) (buffer + AST_FRIENDLY_OFFSET);
+	static struct ast_frame outf = {
+		.frametype = AST_FRAME_VOICE,
+		.subclass = AST_FORMAT_SLINEAR,
+	};
+
+
+	if (!p) {
+		ast_log(LOG_ERROR, "No private structure for %s\n", c->name);
+		return 0;
+	}
+
+	ast_mutex_lock(&p->lock);
+
+	if (p->owner) {
+		while (p->owner && ast_channel_trylock(c)) {
+			ast_debug(1,"Failed to grab lock, trying again\n");
+			ast_mutex_unlock(&p->lock);
+			usleep(1);
+			ast_mutex_lock(&p->lock);
+		}
+		if (!p->owner) {
+			ast_mutex_unlock(&p->lock);
+			ast_log(LOG_ERROR, "Channel has no owner\n");
+			return 0;
+		}
+	} else {
+		ast_mutex_unlock(&p->lock);
+		ast_log(LOG_ERROR, "Channel has no owner\n");
+		return 0;
+	}
+
+
+
+	if (p->faxmode && p->t38_init && p->t38_tx_enable) {
+
+		if ((len = t38_gateway_tx(&p->t38r_state, buf, MAXT30))) {
+
+			outf.samples = len;
+			AST_FRAME_SET_BUFFER(&outf, buffer, AST_FRIENDLY_OFFSET,
+						len * sizeof(int16_t));
+			ast_queue_frame(c, &outf);
+
+		}
+	}
+
+	ast_settimeout(c, 50, t30_read, c);
+	ast_channel_unlock(c);
+	ast_mutex_unlock(&p->lock);
+	return 0;
+}
+
+
+static int t38_tx_packet_handler(t38_core_state_t *s, void *data,
+                		unsigned int* buf, int len, int cout)
+{
+        struct ast_frame f = { AST_FRAME_MODEM, AST_MODEM_T38 };
+        struct ooh323_pvt* p = (struct ooh323_pvt*) data;
+        int res;
+        f.datalen = len;
+        f.data.ptr = buf;
+        f.offset = 0;
+
+        if (gH323Debug)
+         ast_debug(1, "Sending UDPTL packet of %d bytes\n", len);
+        if (p) {
+                ast_mutex_lock(&p->lock);
+                if (p->udptl) {
+                        res = ast_udptl_write(p->udptl, &f);
+                        p->lastTxT38 = time(NULL);
+                }
+                ast_mutex_unlock(&p->lock);
+        }
+        return 0;
+
+}
+
+static void span_message(int level, const char* msg) {
+        if (gH323Debug) ast_debug(1, msg);
+}
+
+
+void onModeChanged(ooCallData *call, int t38mode) {
+        struct ooh323_pvt *p;
+        struct ast_frame f;
+
+	p = find_call(call);
+	if (!p) {
+		ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
+		return;
+	}
+
+	ast_mutex_lock(&p->lock);
+
+	if (gH323Debug)
+       		ast_debug(1, "change mode to %d for %s\n", t38mode, call->callToken);
+
+	if (p->owner) {
+		while (p->owner && ast_channel_trylock(p->owner)) {
+			ast_debug(1,"Failed to grab lock, trying again\n");
+			ast_mutex_unlock(&p->lock);
+			usleep(1);
+			ast_mutex_lock(&p->lock);
+		}
+		if (!p->owner) {
+			ast_mutex_unlock(&p->lock);
+			ast_log(LOG_ERROR, "Channel has no owner\n");
+			return;
+		}
+	} else {
+		ast_mutex_unlock(&p->lock);
+		ast_log(LOG_ERROR, "Channel has no owner\n");
+		return;
+	}
+
+#if 0
+        f.frametype = AST_FRAME_MODEM;
+        f.subclass = 'c';
+        f.datalen = 0;
+        f.samples = 0;
+        f.offset = 0;
+        f.data = NULL;
+        f.mallocd = 0;
+        f.src = "CHANGE_MODE";
+        if (p->owner && !ast_channel_trylock(pvt->owner)) {
+                ast_queue_frame(pvt->owner, &f);
+                ast_mutex_unlock(&pvt->owner->lock);
+        }
+#endif
+
+	if (t38mode) {
+
+		if (t38_gateway_init(&p->t38r_state, t38_tx_packet_handler, p)) {
+			p->t38_init = 1;
+			t38_gateway_set_transmit_on_idle(&p->t38r_state, FALSE);
+			span_log_set_tag(&p->t38r_state.logging, "T.38G");
+			span_log_set_tag(&p->t38r_state.t38.logging, "T.38");
+			span_log_set_message_handler(&p->t38r_state.logging, span_message);
+			span_log_set_message_handler(&p->t38r_state.t38.logging, span_message);
+			span_log_set_level(&p->t38r_state.logging,
+				SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
+			span_log_set_level(&p->t38r_state.t38.logging,
+				SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
+
+			t38_set_t38_version(&p->t38r_state.t38, 0);
+			t38_set_sequence_number_handling(&p->t38r_state.t38,0);
+			t38_gateway_set_ecm_capability(&p->t38r_state, 1);
+			t38_gateway_set_tep_mode(&p->t38r_state, TRUE);
+			t38_gateway_set_supported_modems(&p->t38r_state,
+				T30_SUPPORT_V17 | T30_SUPPORT_V29 | T30_SUPPORT_V27TER);
+			if (gH323Debug)
+				ast_debug(1,"Going to change native format for %s\n", call->callToken);
+			p->owner->nativeformats = AST_FORMAT_SLINEAR;
+			p->owner->rawreadformat = AST_FORMAT_SLINEAR;
+			p->owner->rawwriteformat = AST_FORMAT_SLINEAR;
+			ast_set_read_format(p->owner, p->owner->rawreadformat);
+			ast_set_write_format(p->owner, p->owner->rawwriteformat);
+			p->faxmode = 1;
+			ast_channel_unlock(p->owner);
+			ast_settimeout(p->owner, 50, t30_read, p->owner);
+			ast_channel_lock(p->owner);
+		}
+	} else {
+		p->faxmode = 0;
+		p->t38_init = 0;
+		/* p->chmodepending = 0; */
+	}
+
+
+	ast_channel_unlock(p->owner);
+	ast_mutex_unlock(&p->lock);
+}
+
 
 
 int ooh323_convert_hangupcause_asteriskToH323(int cause)

Modified: team/may/chan_ooh323_rework/addons/chan_ooh323.h
URL: http://svn.asterisk.org/svn-view/asterisk/team/may/chan_ooh323_rework/addons/chan_ooh323.h?view=diff&rev=207350&r1=207349&r2=207350
==============================================================================
--- team/may/chan_ooh323_rework/addons/chan_ooh323.h (original)
+++ team/may/chan_ooh323_rework/addons/chan_ooh323.h Sat Jul 18 21:50:11 2009
@@ -62,6 +62,8 @@
 #include <asterisk/dsp.h>
 #include <asterisk/stringfields.h>
 
+#include <asterisk/udptl.h>
+
 #include "ootypes.h"
 #include "ooCapability.h"
 #include "oochannels.h"

Modified: team/may/chan_ooh323_rework/addons/ooh323c/src/ooCalls.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/may/chan_ooh323_rework/addons/ooh323c/src/ooCalls.c?view=diff&rev=207350&r1=207349&r2=207350
==============================================================================
--- team/may/chan_ooh323_rework/addons/ooh323c/src/ooCalls.c (original)
+++ team/may/chan_ooh323_rework/addons/ooh323c/src/ooCalls.c Sat Jul 18 21:50:11 2009
@@ -98,6 +98,10 @@
 
    if (OO_TESTFLAG(gH323ep.flags, OO_M_MEDIAWAITFORCONN))
       OO_SETFLAG (call->flags, OO_M_MEDIAWAITFORCONN);
+
+// May 20090713. Fix it for Video session
+
+   OO_SETFLAG(call->flags, OO_M_AUDIOSESSION);
    
    call->callState = OO_CALL_CREATED;
    call->callEndReason = OO_REASON_UNKNOWN;
@@ -827,6 +831,23 @@
          }
       }
    }
+   if(type == OO_CAP_TYPE_DATA)
+   {
+      if(!ooGetLogicalChannel(call, 3, dir))
+      {
+         sessionID = 3;
+      }
+      else{
+         if(call->masterSlaveState == OO_MasterSlave_Master)
+            sessionID = call->nextSessionID++;
+         else{
+            sessionID = 0; /* Will be assigned by remote */
+            OOTRACEDBGC4("Session id for %s channel of type data has to be "
+                        "provided by remote.(%s, %s)\n", dir, call->callType, 
+                         call->callToken);
+         }
+      }
+   }
    return sessionID;
 
 }

Modified: team/may/chan_ooh323_rework/addons/ooh323c/src/ooCalls.h
URL: http://svn.asterisk.org/svn-view/asterisk/team/may/chan_ooh323_rework/addons/ooh323c/src/ooCalls.h?view=diff&rev=207350&r1=207349&r2=207350
==============================================================================
--- team/may/chan_ooh323_rework/addons/ooh323c/src/ooCalls.h (original)
+++ team/may/chan_ooh323_rework/addons/ooh323c/src/ooCalls.h Sat Jul 18 21:50:11 2009
@@ -55,6 +55,8 @@
 #define OO_M_MANUALRINGBACK     ASN1UINTCNT(0x10000000)
 
 #define OO_M_TRYBEMASTER	ASN1UINTCNT(0x00000010)
+#define OO_M_AUDIOSESSION	ASN1UINTCNT(0x00000100)
+#define OO_M_DATASESSION	ASN1UINTCNT(0x00000200)
 
 /** 
  * Call states.
@@ -292,6 +294,14 @@
    (struct OOH323CallData *call, const char *dtmf);
 
 /**
+ * This callback function is triggered when dtmf is received over Q.931(keypad)
+ * or H.245(alphanumeric) or H.245(signal). This is not triggered when rfc
+ * 2833 based dtmf is received.
+ */
+typedef int (*cb_OnModeChanged)
+   (struct OOH323CallData *call, int isT38Mode);
+
+/**
  * This structure holds all of the H.323 signaling callback function 
  * addresses.
  * @see ooH323EpSetH323Callbacks
@@ -307,6 +317,7 @@
    cb_OnCallCleared onCallCleared;
    cb_OpenLogicalChannels openLogicalChannels;
    cb_OnReceivedDTMF onReceivedDTMF;
+   cb_OnModeChanged onModeChanged;
 } OOH323CALLBACKS;
 
 /**

Modified: team/may/chan_ooh323_rework/addons/ooh323c/src/ooCapability.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/may/chan_ooh323_rework/addons/ooh323c/src/ooCapability.c?view=diff&rev=207350&r1=207349&r2=207350
==============================================================================
--- team/may/chan_ooh323_rework/addons/ooh323c/src/ooCapability.c (original)
+++ team/may/chan_ooh323_rework/addons/ooh323c/src/ooCapability.c Sat Jul 18 21:50:11 2009
@@ -452,7 +452,6 @@
    return OO_OK;
 }
 
-
 int ooCapabilityAddGSMCapability(OOH323CallData *call, int cap, 
                                 unsigned framesPerPkt, OOBOOL comfortNoise,
                                 OOBOOL scrambled, int dir, 
@@ -544,6 +543,98 @@
       }
    }
 
+   return OO_OK;
+}
+
+/* Used for T38 */
+int ooCapabilityAddT38Capability
+   (OOH323CallData *call, int cap, int dir,
+    cb_StartReceiveChannel startReceiveChannel,
+    cb_StartTransmitChannel startTransmitChannel,
+    cb_StopReceiveChannel stopReceiveChannel,
+    cb_StopTransmitChannel stopTransmitChannel,
+    OOBOOL remote)
+{
+   ooH323EpCapability *epCap = NULL, *cur=NULL;
+   OOCapParams *params=NULL;   
+   OOCTXT *pctxt=NULL;
+   if(!call) pctxt = &gH323ep.ctxt;
+   else pctxt = call->pctxt;
+
+   epCap = (ooH323EpCapability*)memAllocZ(pctxt, sizeof(ooH323EpCapability));
+   params = (OOCapParams*) memAlloc(pctxt, sizeof(OOCapParams));
+   memset(params, 0 , sizeof(OOCapParams));
+   if(!epCap || !params)
+   {
+      OOTRACEERR1("ERROR: Memory - ooCapabilityAddT38Capability - "
+                  "epCap/params\n");
+      return OO_FAILED;
+   }
+
+   if(dir & OORXANDTX) {
+      epCap->dir = OORX;
+      epCap->dir |= OOTX;
+   }
+   else {
+      epCap->dir = dir;
+   }
+   
+   epCap->cap = cap;
+   epCap->capType = OO_CAP_TYPE_DATA;
+   epCap->params = (void*)params;
+   epCap->startReceiveChannel = startReceiveChannel;
+   epCap->startTransmitChannel = startTransmitChannel;
+   epCap->stopReceiveChannel = stopReceiveChannel;
+   epCap->stopTransmitChannel = stopTransmitChannel;
+   epCap->next = NULL;
+
+   if(!call)
+   {
+      /* Add as local capability */
+      OOTRACEDBGC2("Adding endpoint capability %s. \n", 
+                     ooGetCapTypeText(epCap->cap));
+      if(!gH323ep.myCaps) {
+         gH323ep.myCaps = epCap;
+      }
+      else{
+         cur = gH323ep.myCaps;
+         while(cur->next) cur = cur->next;
+         cur->next = epCap;
+      }
+      ooAppendCapToCapPrefs(NULL, cap);
+      gH323ep.noOfCaps++;
+   }
+   else{
+      if(remote)
+      {
+         /* Add as remote capability */
+         if(!call->remoteCaps) {
+            call->remoteCaps = epCap;
+         }
+         else{
+            cur = call->remoteCaps;
+            while(cur->next) cur = cur->next;
+            cur->next = epCap;
+         }
+      }
+      else{
+         /* Add as our capability */
+         OOTRACEDBGC4("Adding call specific capability %s. (%s, %s)\n", 
+                      ooGetCapTypeText(epCap->cap), call->callType, 
+                      call->callToken);
+         if(!call->ourCaps){
+            call->ourCaps = epCap;
+            ooResetCapPrefs(call);
+         }
+         else{
+            cur = call->ourCaps;
+            while(cur->next) cur = cur->next;
+            cur->next = epCap;
+         }
+         ooAppendCapToCapPrefs(call, cap);
+      }
+   }
+           
    return OO_OK;
 }
 
@@ -990,6 +1081,67 @@
    return NULL;
 }
 
+/* This is used for T.38 */
+struct H245DataApplicationCapability* ooCapabilityCreateT38Capability
+   (ooH323EpCapability *epCap, OOCTXT* pctxt, int dir)
+{
+   H245DataApplicationCapability *pT38=NULL;
+   OOCapParams *params;
+   if(!epCap || !epCap->params)
+   {
+     OOTRACEERR1("Error:Invalid capability parameters to "
+                 "ooCapabilityCreateSimpleCapability.\n");
+     return NULL;
+   }
+   params =(OOCapParams*)epCap->params;
+   pT38 = (H245DataApplicationCapability*)memAlloc(pctxt, 
+                                                sizeof(H245DataApplicationCapability));
+   if(!pT38)
+   {
+      OOTRACEERR1("ERROR:Memory - ooCapabilityCreateT38Capability - pT38\n");
+      return NULL;
+   }
+   memset(pT38, 0, sizeof(H245DataApplicationCapability));
+
+   
+   switch(epCap->cap)
+   {
+   case OO_T38:
+      pT38->maxBitRate = 144;
+      pT38->application.t = T_H245DataApplicationCapability_application_t38fax;
+      pT38->application.u.t38fax =
+	(H245DataApplicationCapability_application_t38fax *) memAlloc(pctxt, 
+	sizeof(H245DataApplicationCapability_application_t38fax));
+      if (!pT38->application.u.t38fax) {
+         OOTRACEERR2("Error:Memory - ooCapabilityCreateT38Capability - %d\n", epCap->cap);
+         memFreePtr(pctxt, pT38);
+         return NULL;
+      }
+      memset(pT38->application.u.t38fax, 0, sizeof(H245DataApplicationCapability_application_t38fax));
+      pT38->application.u.t38fax->t38FaxProtocol.t = T_H245DataProtocolCapability_udp;
+      pT38->application.u.t38fax->t38FaxProfile.m.versionPresent = TRUE;
+      pT38->application.u.t38fax->t38FaxProfile.version = 0;
+      pT38->application.u.t38fax->t38FaxProfile.m.t38FaxRateManagementPresent = TRUE;
+      pT38->application.u.t38fax->t38FaxProfile.t38FaxRateManagement.t =
+						T_H245T38FaxRateManagement_transferredTCF;
+      pT38->application.u.t38fax->t38FaxProfile.m.t38FaxUdpOptionsPresent = TRUE;
+      pT38->application.u.t38fax->t38FaxProfile.t38FaxUdpOptions.m.t38FaxMaxBufferPresent = TRUE;
+      pT38->application.u.t38fax->t38FaxProfile.t38FaxUdpOptions.t38FaxMaxBuffer = 200;
+      pT38->application.u.t38fax->t38FaxProfile.t38FaxUdpOptions.m.t38FaxMaxDatagramPresent = TRUE;
+      pT38->application.u.t38fax->t38FaxProfile.t38FaxUdpOptions.t38FaxMaxDatagram = 72;
+      pT38->application.u.t38fax->t38FaxProfile.t38FaxUdpOptions.t38FaxUdpEC.t =
+						T_H245T38FaxUdpOptions_t38FaxUdpEC_t38UDPFEC;
+   
+      return pT38;
+
+   default:
+      OOTRACEERR2("ERROR: Don't know how to create T38 capability %d\n",
+                   epCap->cap);
+   }
+   return NULL;
+}
+
+
 /* Used for g711 ulaw/alaw, g728, g729, g729a, g7231 */
 ASN1BOOL ooCapabilityCheckCompatibility_Simple
    (OOH323CallData *call, ooH323EpCapability* epCap, 
@@ -1179,6 +1331,25 @@
 
 }
 
+OOBOOL ooCapabilityCheckCompatibility_T38
+   (OOH323CallData *call, ooH323EpCapability* epCap, 
+    H245DataApplicationCapability* t38Cap, int dir)
+{
+   unsigned cap = 0;
+   switch(t38Cap->application.t)
+   {
+   case T_H245DataApplicationCapability_application_t38fax:
+      cap = OO_T38;
+      break;
+   default:
+      return FALSE;
+   }
+
+   if(cap != epCap->cap) { return FALSE; }
+
+   return TRUE;
+}
+
 
 OOBOOL ooCapabilityCheckCompatibility_H263Video
    (struct OOH323CallData *call, ooH323EpCapability *epCap, 
@@ -1407,6 +1578,8 @@
                                                    dataType->u.videoData, dir);
       break;
    case T_H245DataType_data:
+      if(epCap->capType == OO_CAP_TYPE_DATA)
+	return ooCapabilityCheckCompatibility_T38(call, epCap, dataType->u.data, dir);
    default:
       OOTRACEDBGC3("ooCapabilityCheckCompatibility - Unsupported  "
                   "capability. (%s, $s)\n", call->callType, call->callToken);
@@ -1930,6 +2103,110 @@
    }   
 }
 
+ooH323EpCapability* ooIsT38Supported
+   (OOH323CallData *call, H245DataApplicationCapability* t38Cap, int dir)
+{
+   int cap = 0;
+   ooH323EpCapability *cur=NULL, *epCap=NULL;
+   OOH263CapParams *params= NULL;
+   /* Find similar capability */
+   switch(t38Cap->application.t)
+   {
+      case T_H245DataApplicationCapability_application_t38fax:
+	 cap = OO_T38;
+	 break;
+      default:
+         return NULL;
+   }   
+
+   if(call->ourCaps)
+     cur = call->ourCaps;
+   else
+     cur = gH323ep.myCaps;
+
+   while(cur)
+   {
+      OOTRACEDBGC4("Local cap being compared %s. (%s, %s)\n", 
+         ooGetCapTypeText(cur->cap),call->callType, call->callToken);
+      
+      if(cur->cap == cap && (cur->dir & dir))
+         break;
+      cur = cur->next;
+   }
+   
+   if(!cur) return NULL;
+   
+   OOTRACEDBGC4("Found matching t38 capability type %s. Comparing"
+                " other parameters. (%s, %s)\n", ooGetCapTypeText(cap), 
+                call->callType, call->callToken);
+   
+   /* can we receive this capability */
+   if(dir & OORX)
+   {
+        OOTRACEDBGC4("We can receive Simple capability %s. (%s, %s)\n", 
+                      ooGetCapTypeText(cur->cap), call->callType, 
+                      call->callToken);
+        epCap = (ooH323EpCapability*)memAllocZ(call->pctxt, 
+                                                 sizeof(ooH323EpCapability));
+        params=(OOCapParams*)memAlloc(call->pctxt,sizeof(OOCapParams));
+        if(!epCap || !params)
+        {
+           OOTRACEERR3("Error:Memory - ooIsT38Supported - "
+                       "epCap/params (%s, %s)\n", call->callType, 
+                       call->callToken);
+           return NULL;
+        }
+        epCap->params = params;
+        epCap->cap = cur->cap;
+        epCap->dir = cur->dir;
+        epCap->capType = cur->capType;
+        epCap->startReceiveChannel = cur->startReceiveChannel;
+        epCap->startTransmitChannel= cur->startTransmitChannel;
+        epCap->stopReceiveChannel = cur->stopReceiveChannel;
+        epCap->stopTransmitChannel = cur->stopTransmitChannel;
+        epCap->next = NULL;
+        memcpy(epCap->params, cur->params, sizeof(OOCapParams));
+        OOTRACEDBGC4("Returning copy of matched receive capability %s. "
+                     "(%s, %s)\n", 
+                     ooGetCapTypeText(cur->cap), call->callType, 
+                     call->callToken);
+        return epCap;
+   }
+
+   /* Can we transmit compatible stream */
+   if(dir & OOTX)
+   {
+      OOTRACEDBGC4("We can transmit Simple capability %s. (%s, %s)\n", 
+                   ooGetCapTypeText(cur->cap), call->callType, 
+                   call->callToken);
+      epCap = (ooH323EpCapability*)memAlloc(call->pctxt, 
+                                                sizeof(ooH323EpCapability));
+      params =(OOCapParams*)memAllocZ(call->pctxt,sizeof(OOCapParams));
+      if(!epCap || !params)
+      {
+         OOTRACEERR3("Error:Memory - ooIsAudioDataTypeSimpleSupported - "
+                     "epCap/params (%s, %s)\n", call->callType, 
+                     call->callToken);
+         return NULL;
+      }
+      epCap->params = params;
+      epCap->cap = cur->cap;
+      epCap->dir = cur->dir;
+      epCap->capType = cur->capType;
+      epCap->startReceiveChannel = cur->startReceiveChannel;
+      epCap->startTransmitChannel= cur->startTransmitChannel;
+      epCap->stopReceiveChannel = cur->stopReceiveChannel;
+      epCap->stopTransmitChannel = cur->stopTransmitChannel;
+      epCap->next = NULL;
+      memcpy(epCap->params, cur->params, sizeof(OOCapParams));
+      OOTRACEDBGC4("Returning copy of matched transmit capability %s."
+                   "(%s, %s)\n", 
+                   ooGetCapTypeText(cur->cap), call->callType, 
+                   call->callToken);
+      return epCap;
+   }
+   return NULL;
+}
 
 ooH323EpCapability* ooIsVideoDataTypeH263Supported
    (OOH323CallData *call, H245H263VideoCapability* pH263Cap, int dir, 
@@ -2130,10 +2407,12 @@
       OOTRACEDBGC3("Looking for audio dataType support. (%s, %s)\n",
                     call->callType, call->callToken);
       return ooIsAudioDataTypeSupported(call, data->u.audioData, dir);
+
    case T_H245DataType_data:
-     OOTRACEDBGC3("Data type not supported.(%s, %s)\n", 
+     OOTRACEDBGC3("Looking for application data dataType support.(%s, %s)\n", 
                    call->callType, call->callToken);
-     return NULL;
+     return ooIsT38Supported(call, data->u.data, dir);
+
    case T_H245DataType_encryptionData:
      OOTRACEDBGC3("Encryption data type not supported.(%s, %s)\n", 
                    call->callType, call->callToken);
@@ -2274,12 +2553,42 @@
    case T_H245Capability_receiveAndTransmitAudioCapability:
      return ooAddRemoteAudioCapability(call, 
                              cap->u.receiveAndTransmitAudioCapability, OORXTX);
+
+
+   case T_H245Capability_receiveDataApplicationCapability:
+     return ooAddRemoteDataApplicationCapability(call, cap->u.receiveDataApplicationCapability, 
+                                       OORX);
+   case T_H245Capability_transmitDataApplicationCapability:
+     return ooAddRemoteDataApplicationCapability(call, cap->u.transmitDataApplicationCapability, 
+                                       OOTX);
+   case T_H245Capability_receiveAndTransmitDataApplicationCapability:
+     return ooAddRemoteDataApplicationCapability(call, 
+                             cap->u.receiveAndTransmitDataApplicationCapability, OORXTX);
+
+
    default:
      OOTRACEDBGA3("Unsupported cap type encountered. Ignoring. (%s, %s)\n", 
                    call->callType, call->callToken);
    }
    return OO_OK;
 }
+
+int ooAddRemoteDataApplicationCapability(OOH323CallData *call, 
+                               H245DataApplicationCapability *dataCap,
+                               int dir)
+{
+   switch(dataCap->application.t)
+   {
+   case T_H245DataApplicationCapability_application_t38fax:
+      return ooCapabilityAddT38Capability(call, OO_T38,
+                            		     dir, NULL, NULL, NULL, NULL,TRUE);
+   default:
+     OOTRACEDBGA1("Unsupported data capability type\n");
+   
+   }
+   return OO_OK;
+}
+
 
 int ooAddRemoteAudioCapability(OOH323CallData *call, 
                                H245AudioCapability *audioCap,
@@ -2442,10 +2751,6 @@
    return OO_OK;
 }
 
-
-
-
-
 int ooCapabilityUpdateJointCapabilities
    (OOH323CallData* call, H245Capability *cap)
 {
@@ -2474,6 +2779,22 @@
    case T_H245Capability_transmitVideoCapability:
       return ooCapabilityUpdateJointCapabilitiesVideo(call, 
                                          cap->u.transmitVideoCapability, OORX);
+
+   case T_H245Capability_receiveDataApplicationCapability:
+      epCap= ooIsT38Supported(call, cap->u.receiveDataApplicationCapability, 
+                                        OOTX);
+      break;
+   case T_H245Capability_transmitDataApplicationCapability:
+      epCap = ooIsT38Supported(call, cap->u.transmitDataApplicationCapability,
+                                        OORX);
+      break;
+   case T_H245Capability_receiveAndTransmitDataApplicationCapability:
+      epCap = ooIsT38Supported(call, cap->u.receiveAndTransmitDataApplicationCapability, OOTX);
+      if (!epCap)
+       epCap = ooIsT38Supported(call, cap->u.receiveAndTransmitDataApplicationCapability, OORX);
+      break;
+
+
    case T_H245Capability_receiveUserInputCapability:
       if((cap->u.receiveUserInputCapability->t == 
                                  T_H245UserInputCapability_basicString) &&
@@ -2686,7 +3007,8 @@
       "OO_H263VIDEO",
       "OO_IS11172VIDEO",  /* mpeg */
       "OO_GENERICVIDEO",
-      "OO_EXTELEMVIDEO"
+      "OO_EXTELEMVIDEO",
+      "OO_T38"		  /* T.38 */
    };
    return ooUtilsGetText (cap, capTypes, OONUMBEROF(capTypes));
 }

Modified: team/may/chan_ooh323_rework/addons/ooh323c/src/ooCapability.h
URL: http://svn.asterisk.org/svn-view/asterisk/team/may/chan_ooh323_rework/addons/ooh323c/src/ooCapability.h?view=diff&rev=207350&r1=207349&r2=207350
==============================================================================
--- team/may/chan_ooh323_rework/addons/ooh323c/src/ooCapability.h (original)
+++ team/may/chan_ooh323_rework/addons/ooh323c/src/ooCapability.h Sat Jul 18 21:50:11 2009
@@ -71,7 +71,8 @@
    OO_H263VIDEO           = 31,
    OO_IS11172VIDEO        = 32,  /* mpeg */
    OO_GENERICVIDEO        = 33,
-   OO_EXTELEMVIDEO        = 34
+   OO_EXTELEMVIDEO        = 34,
+   OO_T38		  = 35
 } OOCapabilities;
 
 

Modified: team/may/chan_ooh323_rework/addons/ooh323c/src/ooh245.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/may/chan_ooh323_rework/addons/ooh323c/src/ooh245.c?view=diff&rev=207350&r1=207349&r2=207350
==============================================================================
--- team/may/chan_ooh323_rework/addons/ooh323c/src/ooh245.c (original)
+++ team/may/chan_ooh323_rework/addons/ooh323c/src/ooh245.c Sat Jul 18 21:50:11 2009
@@ -323,6 +323,7 @@
    ooH323EpCapability *epCap=NULL;
    H245TerminalCapabilitySet *termCap=NULL;
    H245AudioCapability *audioCap=NULL;
+   H245DataApplicationCapability *t38Cap = NULL;
    H245AudioTelephonyEventCapability *ateCap=NULL;
    H245UserInputCapability *userInputCap = NULL;
    H245CapabilityTableEntry *entry=NULL;
@@ -472,6 +473,80 @@
          else{
             entry->capability.t = T_H245Capability_transmitAudioCapability;
             entry->capability.u.transmitAudioCapability = audioCap;
+         }
+         entry->capabilityTableEntryNumber = i+1;
+         dListAppend(pctxt , &(termCap->capabilityTable), entry);
+	 altSetAudio->elem[altSetAudio->n] = i+1;
+	 altSetAudio->n++;
+         i++;
+      }
+      else if(epCap->capType == OO_CAP_TYPE_DATA)
+      {
+
+         /* Create t.38 capability. If capability supports receive, we only 
+            add it as receive capability in TCS. However, if it supports only 
+            transmit, we add it as transmit capability in TCS.
+         */
+         if((epCap->dir & OORX) && !(epCap->dir & OOTX))
+         {
+
+            OOTRACEDBGC3("Sending receive capability t38 in TCS.(%s, %s)\n",
+                call->callType, call->callToken);
+
+            t38Cap = ooCapabilityCreateT38Capability(epCap, pctxt, OORX);
+            if(!t38Cap)
+            {
+               OOTRACEWARN3("WARN:Failed to create t38 capability for"
+                            "%s, %s\n",
+                            call->callType, call->callToken);
+               continue;
+            }
+         }
+         else if((epCap->dir & OOTX) && !(epCap->dir & OORX))
+         {
+            OOTRACEDBGC3("Sending transmit capability t38 in TCS.(%s, %s)\n",
+                call->callType, call->callToken);
+            t38Cap = ooCapabilityCreateT38Capability(epCap, pctxt, OOTX);
+            if(!t38Cap)
+            {
+               OOTRACEWARN3("WARN:Failed to create capability t38 "
+                            "(%s, %s)\n",
+                            call->callType, call->callToken);
+               continue;
+            }     
+         }
+         else{
+            OOTRACEDBGC3("Sending transmit&recevie capability t38 in TCS.(%s, %s)\n",
+                call->callType, call->callToken);
+            t38Cap = ooCapabilityCreateT38Capability(epCap, pctxt, OOTX&OORX);
+            if(!t38Cap)
+            {
+               OOTRACEWARN3("WARN:Failed to create capability t38 "
+                            "(%s, %s)\n",
+                            call->callType, call->callToken);
+               continue;
+            }     
+         }
+         /* Add  Capabilities to Capability Table */
+         entry = (H245CapabilityTableEntry*) memAlloc(pctxt,
+                         sizeof(H245CapabilityTableEntry));
+         if(!entry)
+         {
+            OOTRACEERR3("Error:Memory - ooSendTermCapMsg - entry(audio Cap)."
+                        "(%s, %s)\n", call->callType, call->callToken);
+            return OO_FAILED;
+         }
+         memset(entry, 0, sizeof(H245CapabilityTableEntry));
+         entry->m.capabilityPresent = 1;
+         if((epCap->dir & OORX) && (epCap->dir & OOTX)) {
+            entry->capability.t = T_H245Capability_receiveAndTransmitDataApplicationCapability;
+            entry->capability.u.receiveAndTransmitDataApplicationCapability = t38Cap;
+         } else if((epCap->dir & OORX)) {
+            entry->capability.t = T_H245Capability_receiveDataApplicationCapability;
+            entry->capability.u.receiveDataApplicationCapability = t38Cap;
+         }else{
+            entry->capability.t = T_H245Capability_transmitDataApplicationCapability;
+            entry->capability.u.transmitDataApplicationCapability = t38Cap;
          }
          entry->capabilityTableEntryNumber = i+1;
          dListAppend(pctxt , &(termCap->capabilityTable), entry);
@@ -1092,6 +1167,136 @@
    return OO_OK;
 }
 
+/* handling requestmode routines */
+
+int ooSendRequestModeAck(OOH323CallData* call,

[... 447 lines stripped ...]



More information about the svn-commits mailing list