[asterisk-commits] rizzo: branch rizzo/astobj2 r57961 - /team/rizzo/astobj2/channels/chan_sip.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Mon Mar 5 14:49:49 MST 2007


Author: rizzo
Date: Mon Mar  5 15:49:48 2007
New Revision: 57961

URL: http://svn.digium.com/view/asterisk?view=rev&rev=57961
Log:
partial merge of svn 54838, missing block at line 6608 and below


Modified:
    team/rizzo/astobj2/channels/chan_sip.c

Modified: team/rizzo/astobj2/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/astobj2/channels/chan_sip.c?view=diff&rev=57961&r1=57960&r2=57961
==============================================================================
--- team/rizzo/astobj2/channels/chan_sip.c (original)
+++ team/rizzo/astobj2/channels/chan_sip.c Mon Mar  5 15:49:48 2007
@@ -486,6 +486,7 @@
 #define DEFAULT_TOS_SIP         0               /*!< Call signalling packets should be marked as DSCP CS3, but the default is 0 to be compatible with previous versions. */
 #define DEFAULT_TOS_AUDIO       0               /*!< Audio packets should be marked as DSCP EF (Expedited Forwarding), but the default is 0 to be compatible with previous versions. */
 #define DEFAULT_TOS_VIDEO       0               /*!< Video packets should be marked as DSCP AF41, but the default is 0 to be compatible with previous versions. */
+#define DEFAULT_TOS_TEXT        0               /*!< Text packets should be marked as XXXX XXXX, but the default is 0 to be compatible with previous versions. */
 #define DEFAULT_ALLOW_EXT_DOM	TRUE
 #define DEFAULT_REALM		"asterisk"
 #define DEFAULT_NOTIFYRINGING	TRUE
@@ -554,6 +555,7 @@
 static unsigned int global_tos_sip;		/*!< IP type of service for SIP packets */
 static unsigned int global_tos_audio;		/*!< IP type of service for audio RTP packets */
 static unsigned int global_tos_video;		/*!< IP type of service for video RTP packets */
+static unsigned int global_tos_text;            /*!< IP type of service for text RTP packets */
 static int compactheaders;		/*!< send compact sip headers */
 static int recordhistory;		/*!< Record SIP history. Off by default */
 static int dumphistory;			/*!< Dump history to verbose before destroying SIP dialog */
@@ -825,10 +827,14 @@
 #define SIP_PAGE2_CALL_ONHOLD_INACTIVE	(1 << 24)	/*!< 24: Inactive  */
 #define SIP_PAGE2_RFC2833_COMPENSATE    (1 << 25)	/*!< 25: ???? */
 #define SIP_PAGE2_BUGGY_MWI		(1 << 26)	/*!< 26: Buggy CISCO MWI fix */
+#define SIP_PAGE2_NOTEXT                (1 << 27)       /*!< 26: Text not supported  */
+#define SIP_PAGE2_TEXTSUPPORT           (1 << 28)       /*!< 27: Global text enable */
+#define SIP_PAGE2_DEBUG_TEXT            (1 << 29)       /*!< 28: Global text debug */
 
 #define SIP_PAGE2_FLAGS_TO_COPY \
 	(SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | \
-	SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | SIP_PAGE2_BUGGY_MWI)
+	SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | SIP_PAGE2_BUGGY_MWI | \
+	SIP_PAGE2_TEXTSUPPORT )
 
 /* T.38 set of flags */
 #define T38FAX_FILL_BIT_REMOVAL		(1 << 0)	/*!< Default: 0 (unset)*/
@@ -859,6 +865,7 @@
 #define sipdebug		ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG)
 #define sipdebug_config		ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG_CONFIG)
 #define sipdebug_console	ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG_CONSOLE)
+#define sipdebug_text		ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG_TEXT)
 
 /*! \brief T38 States for a call */
 enum t38state {
@@ -1008,6 +1015,7 @@
 	struct sockaddr_in sa;			/*!< Our peer */
 	struct sockaddr_in redirip;		/*!< Where our RTP should be going if not to us */
 	struct sockaddr_in vredirip;		/*!< Where our Video RTP should be going if not to us */
+	struct sockaddr_in tredirip;            /*!< Where our Text RTP should be going if not to us */
 	time_t lastrtprx;			/*!< Last RTP received */
 	time_t lastrtptx;			/*!< Last RTP sent */
 	int rtptimeout;				/*!< RTP timeout time */
@@ -1036,6 +1044,7 @@
 	struct sip_registry *registry;		/*!< If this is a REGISTER dialog, to which registry */
 	struct ast_rtp *rtp;			/*!< RTP Session */
 	struct ast_rtp *vrtp;			/*!< Video RTP session */
+	struct ast_rtp *trtp;                   /*!< Text RTP session */
 	struct sip_pkt *packets;		/*!< Packets scheduled for re-transmission */
 	struct sip_history_head *history;	/*!< History of this SIP dialog */
 	struct ast_variable *chanvars;		/*!< Channel variables to set for inbound call */
@@ -1677,9 +1686,10 @@
 static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
 
 /*----- RTP interface functions */
-static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active);
+static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active);
 static enum ast_rtp_get_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
 static enum ast_rtp_get_result sip_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
+tatic enum ast_rtp_get_result sip_get_trtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
 static int sip_get_codec(struct ast_channel *chan);
 static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p, int *faxdetect);
 
@@ -1708,6 +1718,7 @@
 	.read = sip_read,		/* called with chan locked */
 	.write = sip_write,		/* called with chan locked */
 	.write_video = sip_write,		/* called with chan locked */
+	.write_text = sip_write,	/* XXX */
 	.indicate = sip_indicate,	/* called with chan locked */
 	.transfer = sip_transfer,		/* called with chan locked */
 	.fixup = sip_fixup,		/* called with chan locked */
@@ -1731,6 +1742,7 @@
 	.read = sip_read,		/* called with chan locked */
 	.write = sip_write,		/* called with chan locked */
 	.write_video = sip_write,		/* called with chan locked */
+	.write_text = sip_write,	/* XXX */
 	.indicate = sip_indicate,	/* called with chan locked */
 	.transfer = sip_transfer,		/* called with chan locked */
 	.fixup = sip_fixup,		/* called with chan locked */
@@ -1778,6 +1790,7 @@
 	type: "SIP",
 	get_rtp_info: sip_get_rtp_peer,
 	get_vrtp_info: sip_get_vrtp_peer,
+	get_trtp_info: sip_get_trtp_peer,
 	set_rtp_peer: sip_set_rtp_peer,
 	get_codec: sip_get_codec,
 };
@@ -3081,6 +3094,11 @@
 			ast_log(LOG_DEBUG, "Setting NAT on UDPTL to %s\n", mode);
 		ast_udptl_setnat(p->udptl, natflags);
 	}
+	if (p->trtp) {
+		if (option_debug)
+			ast_log(LOG_DEBUG, "Setting NAT on TRTP to %s\n", mode);
+		ast_rtp_setnat(p->trtp, natflags);
+	}
 }
 
 /*! \brief Create address structure from peer reference.
@@ -3101,6 +3119,10 @@
 	if ((!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) || !(dialog->capability & AST_FORMAT_VIDEO_MASK)) && dialog->vrtp) {
 		ast_rtp_destroy(dialog->vrtp);
 		dialog->vrtp = NULL;
+	}
+	if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_TEXTSUPPORT) && dialog->trtp) {
+		ast_rtp_destroy(dialog->trtp);
+		dialog->trtp = NULL;
 	}
 	dialog->prefs = peer->prefs;
 	if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) {
@@ -3139,6 +3161,13 @@
 		ast_rtp_set_rtptimeout(dialog->vrtp, peer->rtptimeout);
 		ast_rtp_set_rtpholdtimeout(dialog->vrtp, peer->rtpholdtimeout);
 		ast_rtp_set_rtpkeepalive(dialog->vrtp, peer->rtpkeepalive);
+	}
+	if (dialog->trtp) {
+		ast_rtp_setdtmf(dialog->trtp, 0);
+		ast_rtp_setdtmfcompensate(dialog->trtp, 0);
+		ast_rtp_set_rtptimeout(dialog->trtp, peer->rtptimeout);
+		ast_rtp_set_rtpholdtimeout(dialog->trtp, peer->rtpholdtimeout);
+		ast_rtp_set_rtpkeepalive(dialog->trtp, peer->rtpkeepalive);
 	}
 
 	ast_string_field_set(dialog, peername, peer->username);
@@ -3427,6 +3456,8 @@
 		ast_rtp_destroy(p->rtp);
 	if (p->vrtp)
 		ast_rtp_destroy(p->vrtp);
+	if (p->trtp)
+		ast_rtp_destroy(p->trtp);
 	if (p->udptl)
 		ast_udptl_destroy(p->udptl);
 	sip_refer_destroy(p);
@@ -3908,10 +3939,13 @@
 			if (!p->pendinginvite) {
 				char *audioqos = "";
 				char *videoqos = "";
+				char *textqos = "";
 				if (p->rtp)
 					audioqos = ast_rtp_get_quality(p->rtp);
 				if (p->vrtp)
 					videoqos = ast_rtp_get_quality(p->vrtp);
+				if (p->trtp)
+					textqos = ast_rtp_get_quality(p->trtp);
 				/* Send a hangup */
 				transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
 
@@ -3921,11 +3955,15 @@
 						append_history(p, "RTCPaudio", "Quality:%s", audioqos);
 					if (p->vrtp)
 						append_history(p, "RTCPvideo", "Quality:%s", videoqos);
+					if (p->trtp)
+						append_history(p, "RTCPtext", "Quality:%s", textqos);
 				}
 				if (p->rtp && oldowner)
 					pbx_builtin_setvar_helper(oldowner, "RTPAUDIOQOS", audioqos);
 				if (p->vrtp && oldowner)
 					pbx_builtin_setvar_helper(oldowner, "RTPVIDEOQOS", videoqos);
+				if (p->trtp && oldowner)
+					pbx_builtin_setvar_helper(oldowner, "RTPTEXTQOS", textqos);
 			} else {
 				/* Note we will need a BYE when this all settles out
 				   but we can't send one while we have "INVITE" outstanding. */
@@ -4043,6 +4081,23 @@
 			sip_pvt_unlock(p);
 		}
 		break;
+	case AST_FRAME_TEXT:
+		 if (p) {
+			sip_pvt_lock(p);
+			if (p->trtp) {
+				/* Activate text early media */
+				if ((ast->_state != AST_STATE_UP) &&
+				     !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
+				     !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+					transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE);
+					ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
+				}
+				p->lastrtptx = time(NULL);
+				res = ast_rtp_write(p->trtp, frame);
+			}
+			sip_pvt_unlock(p);
+		 }
+		 break;
 	case AST_FRAME_IMAGE:
 		return 0;
 		break;
@@ -4274,7 +4329,10 @@
 	struct ast_variable *v = NULL;
 	int fmt;
 	int what;
+	int video;
+	int text;
 	int needvideo = 0;
+	int needtext = 0;
 	{
 		const char *my_name;	/* pick a good name */
 	
@@ -4300,15 +4358,22 @@
 
 	/* Select our native format based on codec preference until we receive
 	   something from another device to the contrary. */
-	if (i->jointcapability)	 	/* The joint capabilities of us and peer */
+	if (i->jointcapability) {	 	/* The joint capabilities of us and peer */
 		what = i->jointcapability;
-	else if (i->capability)		/* Our configured capability for this peer */
+		video = i->jointcapability & AST_FORMAT_VIDEO_MASK;
+		text = i->jointcapability & AST_FORMAT_TEXT_MASK;
+	} else if (i->capability) {		/* Our configured capability for this peer */
 		what = i->capability;
-	else
+		video = i->capability & AST_FORMAT_VIDEO_MASK;
+		text = i->capability & AST_FORMAT_TEXT_MASK;
+	} else {
 		what = global_capability;	/* Global codec support */
+		video = global_capability & AST_FORMAT_VIDEO_MASK;
+		text = global_capability & AST_FORMAT_TEXT_MASK;
+	}
 
 	/* Set the native formats for audio  and merge in video */
-	tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
+	tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | video | text;
 	if (option_debug > 2) {
 		char buf[BUFSIZ];
 		ast_log(LOG_DEBUG, "*** Our native formats are %s \n", ast_getformatname_multiple(buf, BUFSIZ, tmp->nativeformats));
@@ -4333,6 +4398,13 @@
 			needvideo = i->jointcapability & AST_FORMAT_VIDEO_MASK;	/* Inbound call */
 	}
 
+	if (i->trtp) {
+		if (i->prefcodec)
+			needtext = i->prefcodec & AST_FORMAT_TEXT_MASK; /* Outbound call */
+		else
+			needtext = i->jointcapability & AST_FORMAT_TEXT_MASK;   /* Inbound call */
+	}
+
 	if (option_debug > 2) {
 		if (needvideo) 
 			ast_log(LOG_DEBUG, "This channel can handle video! HOLLYWOOD next!\n");
@@ -4355,6 +4427,9 @@
 	if (needvideo && i->vrtp) {
 		tmp->fds[2] = ast_rtp_fd(i->vrtp);
 		tmp->fds[3] = ast_rtcp_fd(i->vrtp);
+	}
+	if (needtext && i->trtp) {
+		tmp->fds[4] = ast_rtp_fd(i->trtp);
 	}
 	if (i->udptl) {
 		tmp->fds[5] = ast_udptl_fd(i->udptl);
@@ -4575,6 +4650,19 @@
 	case 3:
 		f = ast_rtcp_read(p->vrtp);	/* RTCP Control Channel for video */
 		break;
+	case 4:
+		f = ast_rtp_read(p->trtp);      /* RTP Text */
+		if (sipdebug_text) {
+			int i;
+			unsigned char* arr = f->data;
+			for (i=0; i < f->datalen; i++)
+				ast_verbose("%c", (arr[i] > ' ' && arr[i] < '}') ? arr[i] : '.');
+			ast_verbose(" -> ");
+			for (i=0; i < f->datalen; i++)
+				ast_verbose("%02X ", arr[i]);
+			ast_verbose("\n");
+		}
+		break;
 	case 5:
 		f = ast_udptl_read(p->udptl);	/* UDPTL for T.38 */
 		break;
@@ -4592,7 +4680,7 @@
 			if (f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) {
 				if (option_debug)
 					ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
-				p->owner->nativeformats = (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass;
+				p->owner->nativeformats = (p->owner->nativeformats & (AST_FORMAT_VIDEO_MASK | AST_FORMAT_TEXT_MASK) ) | f->subclass;
 				ast_set_read_format(p->owner, p->owner->readformat);
 				ast_set_write_format(p->owner, p->owner->writeformat);
 			}
@@ -4766,11 +4854,15 @@
 		/* If the global videosupport flag is on, we always create a RTP interface for video */
 		if (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT))
 			p->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
+		f (ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT))
+			p->trtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
 		if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT))
 			p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr);
-		if (!p->rtp || (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && !p->vrtp)) {
-			ast_log(LOG_WARNING, "Unable to create RTP audio %s session: %s\n",
-				ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "and video" : "", strerror(errno));
+		f (!p->rtp|| (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && !p->vrtp)
+			|| (ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) && !p->trtp)) {
+			ast_log(LOG_WARNING, "Unable to create RTP audio %s%ssession: %s\n",
+				ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "and video " : "",
+				ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "and text " : "", strerror(errno));
 			return __sip_destroy(p);
 		}
 		ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
@@ -4786,6 +4878,11 @@
 			ast_rtp_set_rtptimeout(p->vrtp, global_rtptimeout);
 			ast_rtp_set_rtpholdtimeout(p->vrtp, global_rtpholdtimeout);
 			ast_rtp_set_rtpkeepalive(p->vrtp, global_rtpkeepalive);
+		}
+		if (p->trtp) {
+			ast_rtp_settos(p->trtp, global_tos_text);
+			ast_rtp_setdtmf(p->trtp, 0);
+			ast_rtp_setdtmfcompensate(p->trtp, 0);
 		}
 		if (p->udptl)
 			ast_udptl_settos(p->udptl, global_tos_audio);
@@ -5299,6 +5396,7 @@
 	int len = -1;
 	int portno = -1;		/*!< RTP Audio port number */
 	int vportno = -1;		/*!< RTP Video port number */
+	int tportno = -1;               /*!< RTP Text port number */
 	int udptlportno = -1;
 	int peert38capability = 0;
 	char s[256];
@@ -5307,20 +5405,24 @@
 	/* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */	
 	int peercapability = 0, peernoncodeccapability = 0;
 	int vpeercapability = 0, vpeernoncodeccapability = 0;
+	int tpeercapability = 0, tpeernoncodeccapability = 0;
 	struct sockaddr_in sin;		/*!< media socket address */
 	struct sockaddr_in vsin;	/*!< Video socket address */
+	struct sockaddr_in tsin;        /*!< Text socket address */
 
 	const char *codecs;
 	struct hostent *hp;		/*!< RTP Audio host IP */
 	struct hostent *vhp = NULL;	/*!< RTP video host IP */
+	struct hostent *thp = NULL;     /*!< RTP text host IP */
 	struct ast_hostent audiohp;
 	struct ast_hostent videohp;
+	struct ast_hostent texthp;
 	int codec;
 	int destiterator = 0;
 	int iterator;
 	int sendonly = 0;
 	int numberofports;
-	struct ast_rtp *newaudiortp, *newvideortp;	/* Buffers for codec handling */
+	struct ast_rtp *newaudiortp, *newvideortp, *newtextrtp; /* Buffers for codec handling */
 	int newjointcapability;				/* Negotiated capability */
 	int newpeercapability;
 	int newnoncodeccapability;
@@ -5346,6 +5448,11 @@
 	ast_rtp_new_init(newvideortp);
 	ast_rtp_pt_clear(newvideortp);
 
+	newtextrtp = alloca(ast_rtp_alloc_size());
+	memset(newtextrtp, 0, ast_rtp_alloc_size());
+	ast_rtp_new_init(newtextrtp);
+	ast_rtp_pt_clear(newtextrtp);
+
 	/* Update our last rtprx when we receive an SDP, too */
 	p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */
 
@@ -5372,15 +5479,24 @@
 		return -1;
 	}
 	vhp = hp;	/* Copy to video address as default too */
+	thp = hp;       /* Copy to video address as default too */
 	
 	iterator = req->sdp_start;
 	ast_set_flag(&p->flags[0], SIP_NOVIDEO);	
-
+	ast_set_flag(&p->flags[1], SIP_PAGE2_NOTEXT);
+
+	if (p->vrtp)
+		ast_rtp_pt_clear(newvideortp);  /* Must be cleared in case no m=video line exists */
+
+	if (p->trtp)
+		ast_rtp_pt_clear(newtextrtp);  /* Must be cleared in case no m=text line exists */
 
 	/* Find media streams in this SDP offer */
 	while ((m = get_sdp_iterate(&iterator, req, "m"))[0] != '\0') {
 		int x;
 		int audio = FALSE;
+		int video = FALSE;
+		int text = FALSE;
 
 		numberofports = 1;
 		if ((sscanf(m, "audio %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2) ||
@@ -5401,7 +5517,7 @@
 			}
 		} else if ((sscanf(m, "video %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2) ||
 		    (sscanf(m, "video %d RTP/AVP %n", &x, &len) == 1)) {
-			/* If it is not audio - is it video ? */
+			video = TRUE;
 			ast_clear_flag(&p->flags[0], SIP_NOVIDEO);	
 			numberofmediastreams++;
 			vportno = x;
@@ -5414,6 +5530,22 @@
 				if (debug)
 					ast_verbose("Found RTP video format %d\n", codec);
 				ast_rtp_set_m_type(newvideortp, codec);
+			}
+		} else if ((sscanf(m, "text %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2) ||
+				(sscanf(m, "text %d RTP/AVP %n", &x, &len) == 1)) {
+			text = TRUE;
+			ast_clear_flag(&p->flags[1], SIP_PAGE2_NOTEXT);
+			numberofmediastreams++;
+			tportno = x;
+			/* Scan through the RTP payload types specified in a "m=" line: */
+			for (codecs = m + len; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
+				if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
+					ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
+					return -1;
+				}
+				if (debug)
+					ast_verbose("Found RTP text format %d\n", codec);
+				ast_rtp_set_m_type(newtextrtp, codec);
 			}
 		} else if (p->udptl && ( (sscanf(m, "image %d udptl t38%n", &x, &len) == 1) ||
 					(sscanf(m, "image %d UDPTL t38%n", &x, &len) == 1) )) {
@@ -5447,27 +5579,35 @@
 				if (audio) {
 					if ( !(hp = ast_gethostbyname(host, &audiohp)))
 						ast_log(LOG_WARNING, "Unable to lookup RTP Audio host in secondary c= line, '%s'\n", c);
-				} else if (!(vhp = ast_gethostbyname(host, &videohp)))
-					ast_log(LOG_WARNING, "Unable to lookup RTP video host in secondary c= line, '%s'\n", c);
+				} else if (video) {
+					if (!(vhp = ast_gethostbyname(host, &videohp)))
+						ast_log(LOG_WARNING, "Unable to lookup RTP video host in secondary c= line, '%s'\n", c);
+				} else if (text) {
+					if (!(thp = ast_gethostbyname(host, &texthp)))
+						ast_log(LOG_WARNING, "Unable to lookup RTP text host in secondary c= line, '%s'\n", c);
+				}
 			}
 
 		}
 	}
-	if (portno == -1 && vportno == -1 && udptlportno == -1)
+	if (portno == -1 && vportno == -1 && udptlportno == -1  && tportno == -1)
 		/* No acceptable offer found in SDP  - we have no ports */
 		/* Do not change RTP or VRTP if this is a re-invite */
 		return -2;
 
-	if (numberofmediastreams > 2)
-		/* We have too many fax, audio and/or video media streams, fail this offer */
+	if (numberofmediastreams > 3)
+		/* We have too many fax, audio and/or video and/or text media streams, fail this offer */
 		return -3;
 
 	/* RTP addresses and ports for audio and video */
 	sin.sin_family = AF_INET;
 	vsin.sin_family = AF_INET;
+	tsin.sin_family = AF_INET;
 	memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
 	if (vhp)
 		memcpy(&vsin.sin_addr, vhp->h_addr, sizeof(vsin.sin_addr));
+	if (thp)
+		memcpy(&tsin.sin_addr, thp->h_addr, sizeof(tsin.sin_addr));
 
 	/* Setup UDPTL port number */
 	if (p->udptl) {
@@ -5501,11 +5641,15 @@
 			}
 		}
 	}
-	/* Setup video port number */
+	/* Setup video port number, assumes we have audio */
 	if (vportno != -1)
 		vsin.sin_port = htons(vportno);
 
-	/* Next, scan through each "a=rtpmap:" line, noting each
+	/* Setup text port number, assumes we have audio */
+  	if (tportno != -1)
+  		tsin.sin_port = htons(tportno);
+
+  	/* Next, scan through each "a=xxxx:" line, noting each
 	 * specified RTP payload type (with corresponding MIME subtype):
 	 */
 	/* XXX This needs to be done per media stream, since it's media stream specific */
@@ -5595,10 +5739,18 @@
 			last_rtpmap_codec++;
 
 			/* Note: should really look at the 'freq' and '#chans' params too */
-			ast_rtp_set_rtpmap_type(newaudiortp, codec, "audio", mimeSubtype,
+			/* Note: This should all be done in the context of the m= above */
+			if (!strncasecmp(mimeSubtype, "H26",3)) {         /* Video */
+				/* Not going to do anything here for the moment, but we will soon */
+			} else if (!strncasecmp(mimeSubtype, "T140",4)) { /* Text */
+				if (p->trtp) {
+					/* ast_verbose("Adding t140 mimeSubtype to textrtp struct\n"); */
+					ast_rtp_set_rtpmap_type(newtextrtp, codec, "text", mimeSubtype, 0);
+				}
+			} else {                                          /* Must be audio?? */
+				ast_rtp_set_rtpmap_type(newaudiortp, codec, "audio", mimeSubtype,
 					ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0);
-			if (p->vrtp)
-				ast_rtp_set_rtpmap_type(newvideortp, codec, "video", mimeSubtype, 0);
+			}
 		}
 	}
 	
@@ -5715,21 +5867,23 @@
 	/* Now gather all of the codecs that we are asked for: */
 	ast_rtp_get_current_formats(newaudiortp, &peercapability, &peernoncodeccapability);
 	ast_rtp_get_current_formats(newvideortp, &vpeercapability, &vpeernoncodeccapability);
-
-	newjointcapability = p->capability & (peercapability | vpeercapability);
-	newpeercapability = (peercapability | vpeercapability);
+	ast_rtp_get_current_formats(newtextrtp, &tpeercapability, &tpeernoncodeccapability);
+
+	newjointcapability = p->capability & (peercapability | vpeercapability | tpeercapability);
+	newpeercapability = (peercapability | vpeercapability | tpeercapability);
 	newnoncodeccapability = p->noncodeccapability & peernoncodeccapability;
 		
 		
 	if (debug) {
 		/* shame on whoever coded this.... */
-		char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ], s4[BUFSIZ];
-
-		ast_verbose("Capabilities: us - %s, peer - audio=%s/video=%s, combined - %s\n",
+		char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ], s4[BUFSIZ], s5[BUFSIZ];
+
+		ast_verbose("Capabilities: us - %s, peer - audio=%s/video=%s/text=%s, combined - %s\n",
 			    ast_getformatname_multiple(s1, BUFSIZ, p->capability),
 			    ast_getformatname_multiple(s2, BUFSIZ, newpeercapability),
 			    ast_getformatname_multiple(s3, BUFSIZ, vpeercapability),
-			    ast_getformatname_multiple(s4, BUFSIZ, newjointcapability));
+			    ast_getformatname_multiple(s4, BUFSIZ, tpeercapability),
+			    ast_getformatname_multiple(s5, BUFSIZ, newjointcapability));
 
 		ast_verbose("Non-codec capabilities (dtmf): us - %s, peer - %s, combined - %s\n",
 			    ast_rtp_lookup_mime_multiple(s1, BUFSIZ, p->noncodeccapability, 0, 0),
@@ -5758,6 +5912,8 @@
 	ast_rtp_pt_copy(p->rtp, newaudiortp);
 	if (p->vrtp)
 		ast_rtp_pt_copy(p->vrtp, newvideortp);
+	if (p->trtp)
+		ast_rtp_pt_copy(p->trtp, newtextrtp);
 
 	if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) {
 		ast_clear_flag(&p->flags[0], SIP_DTMF);
@@ -5785,6 +5941,12 @@
 		if (debug) 
 			ast_verbose("Peer video RTP is at port %s:%d\n", ast_inet_ntoa(vsin.sin_addr), ntohs(vsin.sin_port));
 	}
+	/* Setup text port number */
+	if (p->trtp && tsin.sin_port) {
+		ast_rtp_set_peer(p->trtp, &tsin);
+		if (debug)
+			ast_verbose("Peer text RTP is at port %s:%d\n", ast_inet_ntoa(tsin.sin_addr), ntohs(tsin.sin_port));
+	}
 
 	/* Ok, we're going with this offer */
 	if (option_debug > 1) {
@@ -5805,7 +5967,7 @@
 				ast_getformatname_multiple(s1, BUFSIZ, p->jointcapability),
 				ast_getformatname_multiple(s2, BUFSIZ, p->owner->nativeformats));
 		}
-		p->owner->nativeformats = ast_codec_choose(&p->prefs, p->jointcapability, 1) | (p->capability & vpeercapability);
+		p->owner->nativeformats = ast_codec_choose(&p->prefs, p->jointcapability, 1) | (p->capability & vpeercapability) | (p->capability & tpeercapability);
 		ast_set_read_format(p->owner, p->owner->readformat);
 		ast_set_write_format(p->owner, p->owner->writeformat);
 	}
@@ -6535,6 +6697,50 @@
 	if (fmt.cur_ms && (fmt.cur_ms < *min_packet_size))
 		*min_packet_size = fmt.cur_ms;
 
+/*! \brief Add video codec offer to SDP offer/answer body in INVITE or 200 OK */
+  	 /* This is different to the audio one now so we can add more caps later */
+  	 static void add_vcodec_to_sdp(const struct sip_pvt *p, int codec, int sample_rate,
+  	                              char **m_buf, size_t *m_size, char **a_buf, size_t *a_size,
+  	                              int debug, int *min_packet_size)
+  	 {
+  	         int rtp_code;
+  	 
+  	         if (!p->vrtp)
+  	                 return;
+  	 
+  	         if (debug)
+  	                 ast_verbose("Adding video codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec));
+  	 
+  	         if ((rtp_code = ast_rtp_lookup_code(p->vrtp, 1, codec)) == -1)
+  	                 return;
+  	 
+  	         ast_build_string(m_buf, m_size, " %d", rtp_code);
+  	         ast_build_string(a_buf, a_size, "a=rtpmap:%d %s/%d\r\n", rtp_code,
+  	                          ast_rtp_lookup_mime_subtype(1, codec, 0), sample_rate);
+  	         /* Add fmtp code here */
+  	 }
+  	 
+  	 /*! \brief Add text codec offer to SDP offer/answer body in INVITE or 200 OK */
+  	 static void add_tcodec_to_sdp(const struct sip_pvt *p, int codec, int sample_rate,
+  	                              char **m_buf, size_t *m_size, char **a_buf, size_t *a_size,
+  	                              int debug, int *min_packet_size)
+  	 {
+ int rtp_code;
+  	 
+  	         if (!p->trtp)
+  	                 return;
+  	 
+  	         if (debug)
+  	                 ast_verbose("Adding text codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec));
+  	 
+  	         if ((rtp_code = ast_rtp_lookup_code(p->trtp, 1, codec)) == -1)
+  	                 return;
+  	 
+  	         ast_build_string(m_buf, m_size, " %d", rtp_code);
+  	         ast_build_string(a_buf, a_size, "a=rtpmap:%d %s/%d\r\n", rtp_code,
+  	                          ast_rtp_lookup_mime_subtype(1, codec, 0), sample_rate);
+  	         /* Add fmtp code here */
+  	 }
 	/* Our first codec packetization processed cannot be zero */
 	if ((*min_packet_size)==0 && fmt.cur_ms)
 		*min_packet_size = fmt.cur_ms;
@@ -6684,12 +6890,14 @@
 /*! \brief Set all IP media addresses for this call 
 	\note called from add_sdp()
 */
-static void get_our_media_address(struct sip_pvt *p, int needvideo, struct sockaddr_in *sin, struct sockaddr_in *vsin, struct sockaddr_in *dest, struct sockaddr_in *vdest)
+static void get_our_media_address(struct sip_pvt *p, int needvideo, struct sockaddr_in *sin, struct sockaddr_in *vsin, struct sockaddr_in *tsin, struct sockaddr_in *dest, struct sockaddr_in *vdest)
 {
 	/* First, get our address */
 	ast_rtp_get_us(p->rtp, sin);
 	if (p->vrtp)
 		ast_rtp_get_us(p->vrtp, vsin);
+	if (p->trtp)
+  	                 ast_rtp_get_us(p->trtp, tsin);
 
 	/* Now, try to figure out where we want them to send data */
 	/* Is this a re-invite to move the media out, then use the original offer from caller  */
@@ -6723,8 +6931,10 @@
 
 	struct sockaddr_in sin;
 	struct sockaddr_in vsin;
+	struct sockaddr_in tsin;
 	struct sockaddr_in dest;
 	struct sockaddr_in vdest = { 0, };
+	struct sockaddr_in tdest = { 0, };
 
 	/* SDP fields */
 	char *version = 	"v=0\r\n";		/* Protocol version */
@@ -17665,7 +17875,7 @@
 }
 
 /*! \brief Set the RTP peer for this call */
-static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
+static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
 {
 	struct sip_pvt *p = chan->tech_pvt;
 	int changed = 0;
@@ -17700,6 +17910,12 @@
 		changed |= ast_rtp_get_peer(vrtp, &p->vredirip);
 	} else if (p->vredirip.sin_addr.s_addr || ntohs(p->vredirip.sin_port) != 0) {
 		memset(&p->vredirip, 0, sizeof(p->vredirip));
+		changed = 1;
+	}
+	if (trtp) {
+		changed |= ast_rtp_get_peer(trtp, &p->tredirip);
+	} else if (p->tredirip.sin_addr.s_addr || ntohs(p->tredirip.sin_port) != 0) {
+		memset(&p->tredirip, 0, sizeof(p->tredirip));
 		changed = 1;
 	}
 	if (codecs && (p->redircodecs != codecs)) {



More information about the asterisk-commits mailing list