Review Board 1.7.16


Add Connected line interception macros to Asterisk

Review Request #256 - Created May 27, 2009 and submitted

Mark Michelson
/trunk
Reviewers
asterisk-dev
Asterisk
Connected line reception and transmission is a new feature in Asterisk trunk. One of its shortcomings is the inability to modify received connected line information while a dialplan application is running. 

Here is a common example where this may be useful. Many office environments require that a digit (such as '9') is dialled in order to reach the PSTN. The problem is that when one dials a PSTN number, the information received from the far end will not have this prefix digit. To make the lives of users easier, it would be really nice if the prefix digit could be displayed for them.

This proposed patch adds the ability to add connected line interception macros into the dialplan. When we are going to send a connected line update to someone, the administrator has the ability to run a macro which can do whatever manipulation of connected line information is necessary to appease everyone. There are four defined macros in the channelvariables.tex file.

${CONNECTED_LINE_SEND_CALLEE_MACRO}        Macro to call before sending a connected line update to the callee
${CONNECTED_LINE_SEND_CALLEE_MACRO_ARGS}   Arguments to pass to ${CONNECTED_LINE_SEND_CALLEE_MACRO}
${CONNECTED_LINE_SEND_CALLER_MACRO}        Macro to call before sending a connected line update to the caller
${CONNECTED_LINE_SEND_CALLER_MACRO_ARGS}   Arguments to pass to ${CONNECTED_LINE_SEND_CALLER_MACRO}

So in the example I gave above, the administrator could write a simple macro like this:

[macro-addnine]
exten => s,1,Set(CONNECTEDLINE(num,i)=9${CONNECTEDLINE(num)}); Adds '9' to the connected line number

Then, he could add a priority before any Dial to the PSTN:
exten => blah,n,Set(CONNECTED_LINE_SEND_CALLER_MACRO=addnine)

Simple as that! And of course, one is not limited to modifying just the connected line number. You could modify the name, or even information not relating to connected line information.

Please review my code and see if there is anything that needs fixing. I realize as I am typing this that I have not placed anything in the CHANGES file, so I need to do that soon.i
I have tested this with a scenario similar to what I listed above. In addition, I tested features such as call pickup (both using the Pickup application and the pickupexten from features.conf), built-in blind and attended transfers, and SIP transfers.
/trunk/apps/app_dial.c
Revision 198559 New Change
[20] 934 lines
[+20] [+] static struct ast_channel *wait_for_answer(struct ast_channel *in,
935
			if (ast_test_flag64(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) {
935
			if (ast_test_flag64(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) {
936
				if (!peer) {
936
				if (!peer) {
937
					ast_verb(3, "%s answered %s\n", c->name, in->name);
937
					ast_verb(3, "%s answered %s\n", c->name, in->name);
938
					if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
938
					if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
939
						if (o->connected.id.number) {
939
						if (o->connected.id.number) {

    
   
940
							if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
940
							ast_channel_update_connected_line(in, &o->connected);
941
								ast_channel_update_connected_line(in, &o->connected);

    
   
942
							}
941
						} else if (!ast_test_flag64(o, DIAL_NOCONNECTEDLINE)) {
943
						} else if (!ast_test_flag64(o, DIAL_NOCONNECTEDLINE)) {
942
							ast_channel_lock(c);
944
							ast_channel_lock(c);
943
							ast_connected_line_copy_from_caller(&connected_caller, &c->cid);
945
							ast_connected_line_copy_from_caller(&connected_caller, &c->cid);
944
							ast_channel_unlock(c);
946
							ast_channel_unlock(c);
945
							connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
947
							connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
[+20] [20] 39 lines
[+20] static struct ast_channel *wait_for_answer(struct ast_channel *in,
985
					/* This is our guy if someone answered. */
987
					/* This is our guy if someone answered. */
986
					if (!peer) {
988
					if (!peer) {
987
						ast_verb(3, "%s answered %s\n", c->name, in->name);
989
						ast_verb(3, "%s answered %s\n", c->name, in->name);
988
						if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
990
						if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
989
							if (o->connected.id.number) {
991
							if (o->connected.id.number) {

    
   
992
								if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
990
								ast_channel_update_connected_line(in, &o->connected);
993
									ast_channel_update_connected_line(in, &o->connected);

    
   
994
								}
991
							} else if (!ast_test_flag64(o, DIAL_NOCONNECTEDLINE)) {
995
							} else if (!ast_test_flag64(o, DIAL_NOCONNECTEDLINE)) {
992
								ast_channel_lock(c);
996
								ast_channel_lock(c);
993
								ast_connected_line_copy_from_caller(&connected_caller, &c->cid);
997
								ast_connected_line_copy_from_caller(&connected_caller, &c->cid);
994
								ast_channel_unlock(c);
998
								ast_channel_unlock(c);
995
								connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
999
								connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
[+20] [20] 78 lines
[+20] static struct ast_channel *wait_for_answer(struct ast_channel *in,
1074
						ast_party_connected_line_set_init(&connected, &o->connected);
1078
						ast_party_connected_line_set_init(&connected, &o->connected);
1075
						ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
1079
						ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
1076
						ast_party_connected_line_set(&o->connected, &connected);
1080
						ast_party_connected_line_set(&o->connected, &connected);
1077
						ast_party_connected_line_free(&connected);
1081
						ast_party_connected_line_free(&connected);
1078
					} else {
1082
					} else {
1079
						ast_verb(3, "%s connected line has changed, passing it to %s\n", c->name, in->name);
1083
						if (ast_channel_connected_line_macro(c, in, f, 1, 1)) {
1080
						ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
1084
							ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
1081
					}
1085
						}

    
   
1086
					}
1082
					break;
1087
					break;
1083
				case AST_CONTROL_REDIRECTING:
1088
				case AST_CONTROL_REDIRECTING:
1084
					if (ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
1089
					if (ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
1085
						ast_verb(3, "Redirecting update to %s prevented.\n", in->name);
1090
						ast_verb(3, "Redirecting update to %s prevented.\n", in->name);
1086
					} else {
1091
					} else {
[+20] [20] 109 lines
[+20] static struct ast_channel *wait_for_answer(struct ast_channel *in,
1196

    
   
1201

   
1197
			if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF_BEGIN) || (f->frametype == AST_FRAME_DTMF_END)))  {
1202
			if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF_BEGIN) || (f->frametype == AST_FRAME_DTMF_END)))  {
1198
				if (ast_write(outgoing->chan, f))
1203
				if (ast_write(outgoing->chan, f))
1199
					ast_log(LOG_WARNING, "Unable to forward voice or dtmf\n");
1204
					ast_log(LOG_WARNING, "Unable to forward voice or dtmf\n");
1200
			}
1205
			}
1201
			if (single && (f->frametype == AST_FRAME_CONTROL) &&
1206
			if (single && (f->frametype == AST_FRAME_CONTROL)) { 
1202
				((f->subclass == AST_CONTROL_HOLD) ||
1207
				if ((f->subclass == AST_CONTROL_HOLD) ||
1203
				(f->subclass == AST_CONTROL_UNHOLD) ||
1208
				    (f->subclass == AST_CONTROL_UNHOLD) ||
1204
				(f->subclass == AST_CONTROL_VIDUPDATE) ||
1209
				    (f->subclass == AST_CONTROL_VIDUPDATE) ||
1205
				(f->subclass == AST_CONTROL_SRCUPDATE) ||
1210
				    (f->subclass == AST_CONTROL_SRCUPDATE) ||
1206
				(f->subclass == AST_CONTROL_CONNECTED_LINE) ||
1211
				    (f->subclass == AST_CONTROL_REDIRECTING)) {
1207
				(f->subclass == AST_CONTROL_REDIRECTING))) {

   
1208
				ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
1212
					ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
1209
				ast_indicate_data(outgoing->chan, f->subclass, f->data.ptr, f->datalen);
1213
					ast_indicate_data(outgoing->chan, f->subclass, f->data.ptr, f->datalen);

    
   
1214
				} else if (f->subclass == AST_CONTROL_CONNECTED_LINE) {

    
   
1215
					if (ast_channel_connected_line_macro(in, outgoing->chan, f, 0, 1)) {

    
   
1216
						ast_indicate_data(outgoing->chan, f->subclass, f->data.ptr, f->datalen);

    
   
1217
					}

    
   
1218
				}
1210
			}
1219
			}
1211
			ast_frfree(f);
1220
			ast_frfree(f);
1212
		}
1221
		}
1213
		if (!*to)
1222
		if (!*to)
1214
			ast_verb(3, "Nobody picked up in %d ms\n", orig);
1223
			ast_verb(3, "Nobody picked up in %d ms\n", orig);
[+20] [20] 1365 lines
/trunk/apps/app_directed_pickup.c
Revision 198559 New Change
 
/trunk/apps/app_macro.c
Revision 198559 New Change
 
/trunk/apps/app_queue.c
Revision 198559 New Change
 
/trunk/channels/chan_sip.c
Revision 198559 New Change
 
/trunk/doc/tex/channelvariables.tex
Revision 198559 New Change
 
/trunk/include/asterisk/app.h
Revision 198559 New Change
 
/trunk/include/asterisk/channel.h
Revision 198559 New Change
 
/trunk/main/app.c
Revision 198559 New Change
 
/trunk/main/channel.c
Revision 198559 New Change
 
/trunk/main/dial.c
Revision 198559 New Change
 
/trunk/main/features.c
Revision 198559 New Change
 
  1. /trunk/apps/app_dial.c: Loading...
  2. /trunk/apps/app_directed_pickup.c: Loading...
  3. /trunk/apps/app_macro.c: Loading...
  4. /trunk/apps/app_queue.c: Loading...
  5. /trunk/channels/chan_sip.c: Loading...
  6. /trunk/doc/tex/channelvariables.tex: Loading...
  7. /trunk/include/asterisk/app.h: Loading...
  8. /trunk/include/asterisk/channel.h: Loading...
  9. /trunk/main/app.c: Loading...
  10. /trunk/main/channel.c: Loading...
  11. /trunk/main/dial.c: Loading...
  12. /trunk/main/features.c: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.