1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** all actions (and hangup) are processed here **
10 \*****************************************************************************/
18 #include "linux/isdnif.h"
20 extern char **environ;
23 /* create caller id from digits by comparing with national and international
26 char *nationalize_callerinfo(char *string, int *ntype)
28 if (!strncmp(options.international, string, strlen(options.international)))
30 *ntype = INFO_NTYPE_INTERNATIONAL;
31 return(string+strlen(options.international));
33 if (!strncmp(options.national, string, strlen(options.national)))
35 *ntype = INFO_NTYPE_NATIONAL;
36 return(string+strlen(options.national));
38 *ntype = INFO_NTYPE_SUBSCRIBER;
42 /* create number (including access codes) from caller id
45 char *numberrize_callerinfo(char *string, int ntype)
47 static char result[256];
51 case INFO_NTYPE_INTERNATIONAL:
52 UCPY(result, options.international);
57 case INFO_NTYPE_NATIONAL:
58 UCPY(result, options.national);
70 * process init 'internal' / 'external' / 'chan' / 'vbox-record' / 'partyline'...
72 void EndpointAppPBX::_action_init_call(int chan)
75 struct port_list *portlist = ea_endpoint->ep_portlist;
77 /* a created call, this should never happen */
78 if (ea_endpoint->ep_call_id)
80 if (options.deb & DEBUG_EPOINT)
81 PERROR("EPOINT(%d): We already have a call instance, this should never happen!\n", ea_endpoint->ep_serial);
86 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new call instance.\n", ea_endpoint->ep_serial);
88 call = new CallChan(ea_endpoint);
90 call = new CallPBX(ea_endpoint);
93 /* resource not available */
94 message_disconnect_port(portlist, CAUSE_RESSOURCEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
95 new_state(EPOINT_STATE_OUT_DISCONNECT);
96 set_tone(portlist,"cause_22");
99 ea_endpoint->ep_call_id = call->c_serial;
101 void EndpointAppPBX::action_init_call(void)
103 _action_init_call(0);
105 void EndpointAppPBX::action_init_chan(void)
107 _action_init_call(1);
111 * process dialing 'internal'
113 void EndpointAppPBX::action_dialing_internal(void)
115 struct capa_info capainfo;
116 struct caller_info callerinfo;
117 struct redir_info redirinfo;
118 struct dialing_info dialinginfo;
119 struct port_list *portlist = ea_endpoint->ep_portlist;
120 struct message *message;
121 struct extension ext;
122 struct route_param *rparam;
124 /* send proceeding, because number is complete */
125 set_tone(portlist, "proceeding");
126 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
127 message_put(message);
129 new_state(EPOINT_STATE_IN_PROCEEDING);
131 /* create bearer/caller/dialinginfo */
132 memcpy(&capainfo, &e_capainfo, sizeof(capainfo));
133 memcpy(&callerinfo, &e_callerinfo, sizeof(callerinfo));
134 memcpy(&redirinfo, &e_redirinfo, sizeof(redirinfo));
135 memset(&dialinginfo, 0, sizeof(dialinginfo));
136 dialinginfo.itype = INFO_ITYPE_INTERN;
137 SCPY(dialinginfo.number, e_dialinginfo.number);
139 /* process extension */
140 if ((rparam = routeparam(e_action, PARAM_EXTENSION)))
141 SCPY(dialinginfo.number, rparam->string_value);
143 /* process number type */
144 if ((rparam = routeparam(e_action, PARAM_TYPE)))
145 dialinginfo.ntype = rparam->integer_value;
147 /* process service */
148 if ((rparam = routeparam(e_action, PARAM_CAPA)))
150 capainfo.bearer_capa = rparam->integer_value;
151 if (capainfo.bearer_capa != INFO_BC_SPEECH
152 && capainfo.bearer_capa != INFO_BC_AUDIO)
154 capainfo.bearer_mode = INFO_BMODE_PACKET;
156 capainfo.bearer_info1 = INFO_INFO1_NONE;
158 if ((rparam = routeparam(e_action, PARAM_BMODE)))
160 capainfo.bearer_mode = rparam->integer_value;
162 if ((rparam = routeparam(e_action, PARAM_INFO1)))
164 capainfo.bearer_info1 = rparam->integer_value;
166 if ((rparam = routeparam(e_action, PARAM_HLC)))
168 capainfo.hlc = rparam->integer_value;
170 if ((rparam = routeparam(e_action, PARAM_EXTHLC)))
172 capainfo.exthlc = rparam->integer_value;
175 /* process presentation */
176 if ((rparam = routeparam(e_action, PARAM_PRESENT)))
178 callerinfo.present = (rparam->integer_value)?INFO_PRESENT_ALLOWED:INFO_PRESENT_RESTRICTED;
181 /* check if extension exists AND only if not multiple extensions */
182 if (!read_extension(&ext, dialinginfo.number) && !strchr(dialinginfo.number,','))
184 printlog("%3d action INTERN dialed extension %s doesn't exist.\n", ea_endpoint->ep_serial, dialinginfo.number);
185 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): extension %s doesn't exist\n", ea_endpoint->ep_serial, dialinginfo.number);
186 new_state(EPOINT_STATE_OUT_DISCONNECT);
187 message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, "");
188 set_tone(portlist, "cause_86");
191 /* check if internal calls are denied */
192 if (e_ext.rights < 1)
194 printlog("%3d action INTERN access to internal phones are denied for this caller.\n", ea_endpoint->ep_serial);
195 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): internal call from terminal %s denied.\n", ea_endpoint->ep_serial, e_terminal);
196 new_state(EPOINT_STATE_OUT_DISCONNECT);
197 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
198 set_tone(portlist, "cause_81");
202 /* add or update internal call */
203 printlog("%3d action INTERN call to extension %s.\n", ea_endpoint->ep_serial, dialinginfo.number);
204 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP);
205 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
206 memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info));
207 memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info));
208 memcpy(&message->param.setup.capainfo, &capainfo, sizeof(struct capa_info));
209 message_put(message);
212 /* process dialing external
214 void EndpointAppPBX::action_dialing_external(void)
216 struct capa_info capainfo;
217 struct caller_info callerinfo;
218 struct redir_info redirinfo;
219 struct dialing_info dialinginfo;
221 struct port_list *portlist = ea_endpoint->ep_portlist;
222 struct message *message;
223 struct route_param *rparam;
225 /* special processing of delete characters '*' and '#' */
226 if (e_ext.delete_ext)
228 /* dialing a # causes a clearing of complete number */
229 if (strchr(e_extdialing, '#'))
231 e_extdialing[0] = '\0';
232 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): '#' detected: terminal '%s' selected caller id '%s' and continues dialing: '%s'\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, e_extdialing);
234 /* eliminate digits before '*', which is a delete digit
236 if (strchr(e_extdialing, '*'))
239 while((p=strchr(e_extdialing, '*')))
241 if (p > e_extdialing) /* only if there is a digit in front */
246 UCPY(p, p+1); /* remove '*' */
248 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s deleted digits and got new string: %s\n", ea_endpoint->ep_serial, e_terminal, e_extdialing);
252 /* create bearer/caller/dialinginfo */
253 memcpy(&capainfo, &e_capainfo, sizeof(capainfo));
254 memcpy(&callerinfo, &e_callerinfo, sizeof(callerinfo));
255 memcpy(&redirinfo, &e_redirinfo, sizeof(redirinfo));
256 memset(&dialinginfo, 0, sizeof(dialinginfo));
257 dialinginfo.itype = INFO_ITYPE_EXTERN;
258 dialinginfo.sending_complete = 0;
259 SCPY(dialinginfo.number, e_extdialing);
262 if ((rparam = routeparam(e_action, PARAM_PREFIX)))
263 SPRINT(dialinginfo.number, "%s%s", rparam->string_value, e_extdialing);
265 /* process number complete */
266 if ((rparam = routeparam(e_action, PARAM_COMPLETE)))
267 if ((rparam = routeparam(e_action, PARAM_PREFIX)))
268 SCPY(dialinginfo.number, rparam->string_value);
269 dialinginfo.sending_complete = 1;
271 /* process number type */
272 if ((rparam = routeparam(e_action, PARAM_TYPE)))
273 dialinginfo.ntype = rparam->integer_value;
275 /* process service */
276 if ((rparam = routeparam(e_action, PARAM_CAPA)))
278 capainfo.bearer_capa = rparam->integer_value;
279 if (capainfo.bearer_capa != INFO_BC_SPEECH
280 && capainfo.bearer_capa != INFO_BC_AUDIO)
282 capainfo.bearer_mode = INFO_BMODE_PACKET;
284 capainfo.bearer_info1 = INFO_INFO1_NONE;
286 if ((rparam = routeparam(e_action, PARAM_BMODE)))
288 capainfo.bearer_mode = rparam->integer_value;
290 if ((rparam = routeparam(e_action, PARAM_INFO1)))
292 capainfo.bearer_info1 = rparam->integer_value;
294 if ((rparam = routeparam(e_action, PARAM_HLC)))
296 capainfo.hlc = rparam->integer_value;
298 if ((rparam = routeparam(e_action, PARAM_EXTHLC)))
300 capainfo.exthlc = rparam->integer_value;
304 /* process callerid */
305 if ((rparam = routeparam(e_action, PARAM_CALLERID)))
307 SCPY(callerinfo.id, rparam->string_value);
309 if ((rparam = routeparam(e_action, PARAM_CALLERIDTYPE)))
311 callerinfo.ntype = rparam->integer_value;
314 /* process presentation */
315 if ((rparam = routeparam(e_action, PARAM_PRESENT)))
317 callerinfo.present = (rparam->integer_value)?INFO_PRESENT_ALLOWED:INFO_PRESENT_RESTRICTED;
320 /* process interfaces */
321 if ((rparam = routeparam(e_action, PARAM_INTERFACES)))
322 SCPY(dialinginfo.interfaces, rparam->string_value);
324 /* check if local calls are denied */
325 if (e_ext.rights < 2)
327 printlog("%3d action EXTERN calls are denied for this caller.\n", ea_endpoint->ep_serial);
328 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): external call from terminal denied: %s\n", ea_endpoint->ep_serial, e_terminal);
329 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, 0);
330 set_tone(portlist, "cause_82");
332 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
333 new_state(EPOINT_STATE_OUT_DISCONNECT);
337 if (!strncmp(dialinginfo.number, options.national, strlen(options.national))
338 || dialinginfo.ntype == INFO_NTYPE_NATIONAL
339 || dialinginfo.ntype == INFO_NTYPE_INTERNATIONAL)
341 /* check if national calls are denied */
342 if (e_ext.rights < 3)
344 printlog("%3d action EXTERN national calls are denied for this caller.\n", ea_endpoint->ep_serial);
345 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): national call from terminal %s denied.\n", ea_endpoint->ep_serial, e_terminal);
346 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, 0);
347 set_tone(portlist, "cause_83");
352 if (!strncmp(dialinginfo.number, options.international, strlen(options.international))
353 || dialinginfo.ntype == INFO_NTYPE_INTERNATIONAL)
355 /* check if international calls are denied */
356 if (e_ext.rights < 4)
358 printlog("%3d action EXTERN international calls are denied for this caller.\n", ea_endpoint->ep_serial);
359 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): international call from terminal %s denied.\n", ea_endpoint->ep_serial, e_terminal);
360 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, 0);
361 set_tone(portlist, "cause_84");
366 /* add or update outgoing call */
367 printlog("%3d action EXTERN call to destination %s.\n", ea_endpoint->ep_serial, dialinginfo.number);
368 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP);
369 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
370 memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info));
371 memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info));
372 memcpy(&message->param.setup.capainfo, &capainfo, sizeof(struct capa_info));
373 message_put(message);
377 void EndpointAppPBX::action_dialing_chan(void)
379 struct port_list *portlist = ea_endpoint->ep_portlist;
381 printlog("%3d action channel API not implemented.\n", ea_endpoint->ep_serial);
382 message_disconnect_port(portlist, CAUSE_UNIMPLEMENTED, LOCATION_PRIVATE_LOCAL, "");
383 new_state(EPOINT_STATE_OUT_DISCONNECT);
384 set_tone(portlist,"cause_4f");
389 * process dialing the "am" and record
391 void EndpointAppPBX::action_dialing_vbox_record(void)
393 struct dialing_info dialinginfo;
394 struct port_list *portlist = ea_endpoint->ep_portlist;
395 struct message *message;
396 struct extension ext;
397 struct route_param *rparam;
399 portlist = ea_endpoint->ep_portlist;
401 /* check for given extension */
402 if (!(rparam = routeparam(e_action, PARAM_EXTENSION)))
404 printlog("%3d action VBOX-RECORD extension not given by parameter.\n", ea_endpoint->ep_serial);
405 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): cannot record, because no 'extension' parameter has been specified.\n", ea_endpoint->ep_serial);
407 new_state(EPOINT_STATE_OUT_DISCONNECT);
408 message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
409 set_tone(portlist, "cause_3f");
413 /* check if extension exists */
414 if (!read_extension(&ext, rparam->string_value))
416 printlog("%3d action VBOX-RECORD given extension %s doesn't exist.\n", ea_endpoint->ep_serial, rparam->string_value);
417 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): extension %s doesn't exist\n", ea_endpoint->ep_serial, rparam->string_value);
418 new_state(EPOINT_STATE_OUT_DISCONNECT);
419 message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, "");
420 set_tone(portlist, "cause_86");
424 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s dialing extension: %s\n", ea_endpoint->ep_serial, e_terminal, rparam->string_value);
426 /* check if internal calls are denied */
427 if (e_ext.rights < 1)
429 printlog("%3d action VBOX-RECORD calls are denied for this caller.\n", ea_endpoint->ep_serial);
430 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): internal call from terminal %s denied.\n", ea_endpoint->ep_serial, e_terminal);
431 new_state(EPOINT_STATE_OUT_DISCONNECT);
432 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
433 set_tone(portlist, "cause_81");
437 set_tone(portlist, "proceeding");
438 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
439 message_put(message);
441 new_state(EPOINT_STATE_IN_PROCEEDING);
443 memset(&dialinginfo, 0, sizeof(dialinginfo));
444 dialinginfo.itype = INFO_ITYPE_VBOX;
445 dialinginfo.sending_complete = 1;
446 SCPY(dialinginfo.number, rparam->string_value);
448 /* append special announcement (if given) */
449 if ((rparam = routeparam(e_action, PARAM_ANNOUNCEMENT)))
450 if (rparam->string_value[0])
452 SCAT(dialinginfo.number, ",");
453 SCAT(dialinginfo.number, rparam->string_value);
456 /* add or update internal call */
457 printlog("%3d action VBOX-RECORD call to extension %s.\n", ea_endpoint->ep_serial, dialinginfo.number);
458 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP);
459 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
460 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
461 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
462 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
463 message_put(message);
470 void EndpointAppPBX::action_init_partyline(void)
473 class CallPBX *callpbx;
474 struct port_list *portlist = ea_endpoint->ep_portlist;
475 struct message *message;
476 struct route_param *rparam;
478 struct call_relation *relation;
480 portlist = ea_endpoint->ep_portlist;
482 /* check for given extension */
483 if (!(rparam = routeparam(e_action, PARAM_ROOM)))
485 printlog("%3d action PARTYLINE no 'room' parameter given at routing.\n", ea_endpoint->ep_serial);
486 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): missing parameter 'room'.\n", ea_endpoint->ep_serial);
488 new_state(EPOINT_STATE_OUT_DISCONNECT);
489 message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
490 set_tone(portlist, "cause_3f");
493 if (rparam->integer_value <= 0)
495 printlog("%3d action PARTYLINE 'room' value must be greate 0.\n", ea_endpoint->ep_serial);
496 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): invalid value for 'room'.\n", ea_endpoint->ep_serial);
499 partyline = rparam->integer_value;
501 /* don't create call if partyline exists */
505 if (call->c_type == CALL_TYPE_PBX)
507 callpbx = (class CallPBX *)call;
508 if (callpbx->c_partyline == rparam->integer_value)
516 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new call instance.\n", ea_endpoint->ep_serial);
517 if (!(call = new CallPBX(ea_endpoint)))
520 /* resource not available */
521 message_disconnect_port(portlist, CAUSE_RESSOURCEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
522 new_state(EPOINT_STATE_OUT_DISCONNECT);
523 set_tone(portlist,"cause_22");
528 //NOTE: callpbx must be set here
529 /* add relation to existing call */
530 if (!(relation=callpbx->add_relation()))
534 relation->type = RELATION_TYPE_SETUP;
535 relation->channel_state = CHANNEL_STATE_CONNECT;
536 relation->rx_state = NOTIFY_STATE_ACTIVE;
537 relation->tx_state = NOTIFY_STATE_ACTIVE;
538 relation->epoint_id = ea_endpoint->ep_serial;
541 ea_endpoint->ep_call_id = call->c_serial;
543 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s dialing room: %d\n", ea_endpoint->ep_serial, e_terminal, partyline);
545 set_tone(portlist, "proceeding");
546 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
547 message_put(message);
549 new_state(EPOINT_STATE_IN_PROCEEDING);
551 /* send setup to call */
552 printlog("%3d action PARTYLINE call to room %d.\n", ea_endpoint->ep_serial, partyline);
553 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP);
554 message->param.setup.partyline = partyline;
555 memcpy(&message->param.setup.dialinginfo, &e_dialinginfo, sizeof(struct dialing_info));
556 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
557 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
558 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
559 message_put(message);
564 * process hangup of all calls
566 void EndpointAppPBX::action_hangup_call(void)
570 printlog("%3d action CALL to '%s' hangs up.\n", ea_endpoint->ep_serial, e_dialinginfo.number);
572 if (e_terminal[0] == '\0')
574 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last dialed number '%s' because caller is unknown (not internal).\n", ea_endpoint->ep_serial, e_terminal, e_dialinginfo.number);
577 if (!(read_extension(&e_ext, e_terminal)))
579 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last dialed number '%s' because cannot read settings.\n", ea_endpoint->ep_serial, e_terminal, e_dialinginfo.number);
582 if (e_dialinginfo.number[0] == '\0')
584 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last dialed number because nothing was dialed.\n", ea_endpoint->ep_serial, e_terminal);
587 if (!strcmp(e_dialinginfo.number, e_ext.last_out[0]))
589 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last dialed number '%s' because it is identical with the last one.\n", ea_endpoint->ep_serial, e_terminal, e_dialinginfo.number);
594 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: storing last number '%s'.\n", ea_endpoint->ep_serial, e_terminal, e_dialinginfo.number);
598 UCPY(e_ext.last_out[i], e_ext.last_out[i-1]);
601 SCPY(e_ext.last_out[0], e_dialinginfo.number);
603 /* write extension */
604 write_extension(&e_ext, e_terminal);
609 * process dialing 'login'
611 void EndpointAppPBX::action_dialing_login(void)
613 struct port_list *portlist = ea_endpoint->ep_portlist;
614 struct message *message;
616 struct route_param *rparam;
618 /* extension parameter */
619 if ((rparam = routeparam(e_action, PARAM_EXTENSION)))
621 /* extension is given by parameter */
622 extension = rparam->string_value;
623 if (extension[0] == '\0')
625 if (!read_extension(&e_ext, extension))
627 printlog("%3d action LOGIN given extension %s doesn't exist.\n", ea_endpoint->ep_serial, extension);
628 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): given extension %s not found.\n", ea_endpoint->ep_serial, extension);
629 /* extension doesn't exist */
630 new_state(EPOINT_STATE_OUT_DISCONNECT);
631 message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, "");
632 set_tone(portlist, "cause_86");
637 /* extension must be given by dialstring */
638 extension = e_extdialing;
639 if (extension[0] == '\0')
641 if (!read_extension(&e_ext, extension))
643 printlog("%3d action LOGIN given extension %s incomplete or not found..\n", ea_endpoint->ep_serial, extension);
644 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): extension %s incomplete or not found\n", ea_endpoint->ep_serial, extension);
649 /* we changed our extension */
650 SCPY(e_terminal, extension);
651 new_state(EPOINT_STATE_CONNECT);
655 /* send connect with extension's caller id (COLP) */
656 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
657 SCPY(message->param.connectinfo.id, e_ext.callerid);
658 message->param.connectinfo.ntype = e_ext.callerid_type;
659 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
660 message->param.connectinfo.present = INFO_PRESENT_RESTRICTED;
661 else message->param.connectinfo.present = e_ext.callerid_present;
662 /* handle restricted caller ids */
663 apply_callerid_restriction(e_ext.anon_ignore, portlist->port_type, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name);
664 /* display callerid if desired for extension */
665 SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype, message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name));
666 message->param.connectinfo.ntype = e_ext.callerid_type;
667 message_put(message);
670 /* set our caller id */
671 SCPY(e_callerinfo.id, e_ext.callerid);
672 e_callerinfo.ntype = e_ext.callerid_type;
673 e_callerinfo.present = e_ext.callerid_present;
675 /* enable connectedmode */
679 if (!(rparam = routeparam(e_action, PARAM_NOPASSWORD)))
681 /* make call state to enter password */
682 printlog("%3d action LOGIN to extension %s, ask for password.\n", ea_endpoint->ep_serial, e_terminal);
683 new_state(EPOINT_STATE_IN_OVERLAP);
686 e_action = &action_password;
688 e_match_to_action = NULL;
689 e_dialinginfo.number[0] = '\0';
690 e_extdialing = strchr(e_dialinginfo.number, '\0');
693 e_password_timeout = now+20;
699 /* make call state */
700 new_state(EPOINT_STATE_IN_OVERLAP);
701 e_ruleset = ruleset_main;
703 e_rule = e_ruleset->rule_first;
705 e_dialinginfo.number[0] = '\0';
706 e_extdialing = e_dialinginfo.number;
707 set_tone(portlist, "dialpbx");
713 * process init 'change_callerid'
715 void EndpointAppPBX::action_init_change_callerid(void)
717 struct port_list *portlist = ea_endpoint->ep_portlist;
719 if (!e_ext.change_callerid)
721 /* service not available */
722 printlog("%3d action CHANGE-CALLERID denied for this caller.\n", ea_endpoint->ep_serial);
723 message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
724 new_state(EPOINT_STATE_OUT_DISCONNECT);
725 set_tone(portlist,"cause_87");
730 /* process dialing callerid
732 void EndpointAppPBX::_action_callerid_calleridnext(int next)
734 struct port_list *portlist = ea_endpoint->ep_portlist;
735 struct route_param *rparam;
736 char buffer[64], *callerid;
738 if ((rparam = routeparam(e_action, PARAM_CALLERID)))
740 /* the caller ID is given by parameter */
741 callerid = rparam->string_value;
744 /* caller ID is dialed */
745 if (!strchr(e_extdialing, '#'))
747 /* no complete ID yet */
750 *strchr(e_extdialing, '#') = '\0';
751 callerid = e_extdialing;
754 /* given callerid type */
755 if ((rparam = routeparam(e_action, PARAM_CALLERIDTYPE)))
756 switch(rparam->integer_value)
758 case INFO_NTYPE_SUBSCRIBER:
759 SPRINT(buffer, "s%s", callerid);
762 case INFO_NTYPE_NATIONAL:
763 SPRINT(buffer, "n%s", callerid);
766 case INFO_NTYPE_INTERNATIONAL:
767 SPRINT(buffer, "i%s", callerid);
771 SPRINT(buffer, "%s", callerid);
776 /* caller id complete, dialing with new caller id */
777 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: storing callerid '%s' for all following calls.\n", ea_endpoint->ep_serial, e_terminal, callerid);
778 /* write new parameters */
779 if (read_extension(&e_ext, e_terminal))
781 if (callerid[0] == '\0')
784 (!next)?e_ext.callerid_present:e_ext.id_next_call_present = INFO_PRESENT_RESTRICTED;
788 (!next)?e_ext.callerid_present:e_ext.id_next_call_present = INFO_PRESENT_ALLOWED;
789 if ((rparam = routeparam(e_action, PARAM_PRESENT))) if (rparam->integer_value == 0)
790 (!next)?e_ext.callerid_present:e_ext.id_next_call_present = INFO_PRESENT_RESTRICTED;
791 if (e_ext.callerid_type == INFO_NTYPE_UNKNOWN) /* if callerid is unknown, the given id is not nationalized */
793 SCPY((!next)?e_ext.callerid:e_ext.id_next_call, callerid);
794 (!next)?e_ext.callerid_type:e_ext.id_next_call_type = INFO_NTYPE_UNKNOWN;
797 SCPY((!next)?e_ext.callerid:e_ext.id_next_call, nationalize_callerinfo(callerid,&((!next)?e_ext.callerid_type:e_ext.id_next_call_type)));
799 if (!next) e_ext.id_next_call_type = -1;
800 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): nationalized callerid: '%s' type=%d\n", ea_endpoint->ep_serial, (!next)?e_ext.callerid:e_ext.id_next_call, (!next)?e_ext.callerid_type:e_ext.id_next_call_type);
802 write_extension(&e_ext, e_terminal);
805 /* function activated */
806 printlog("%3d action CHANGE-CALLERID caller changes caller id%s to '%s'.\n", ea_endpoint->ep_serial, next?" of next call":"", callerid);
807 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
808 new_state(EPOINT_STATE_OUT_DISCONNECT);
809 set_tone(portlist,"activated");
812 /* process dialing callerid for all call
814 void EndpointAppPBX::action_dialing_callerid(void)
816 _action_callerid_calleridnext(0);
819 /* process dialing callerid for next call
821 void EndpointAppPBX::action_dialing_calleridnext(void)
823 _action_callerid_calleridnext(1);
828 * process init 'change_forward'
830 void EndpointAppPBX::action_init_change_forward(void)
832 struct port_list *portlist = ea_endpoint->ep_portlist;
834 if (!e_ext.change_forward)
836 printlog("%3d action CHANGE-FORWARD denied for this caller.\n", ea_endpoint->ep_serial);
837 /* service not available */
838 message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
839 new_state(EPOINT_STATE_OUT_DISCONNECT);
840 set_tone(portlist,"cause_87");
845 /* process dialing forwarding
847 void EndpointAppPBX::action_dialing_forward(void)
849 struct port_list *portlist = ea_endpoint->ep_portlist;
850 int diversion = INFO_DIVERSION_CFU;
851 char *dest = e_extdialing;
852 struct route_param *rparam;
854 /* if diversion type is given */
855 if ((rparam = routeparam(e_action, PARAM_DIVERSION)))
856 diversion = rparam->integer_value;
858 if ((rparam = routeparam(e_action, PARAM_DEST)))
860 /* if destination is given */
861 dest = rparam->string_value;
864 if (!strchr(e_extdialing, '#'))
866 *strchr(e_extdialing, '#') = '\0';
870 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: storing forwarding to '%s'.\n", ea_endpoint->ep_serial, e_terminal, dest);
871 if (read_extension(&e_ext, e_terminal))
875 case INFO_DIVERSION_CFU:
876 printlog("%3d action CHANGE-FORWARD changing CFU (unconditional) to '%s'.\n", ea_endpoint->ep_serial, dest);
877 SCPY(e_ext.cfu, dest);
879 case INFO_DIVERSION_CFB:
880 printlog("%3d action CHANGE-FORWARD changing CFB (busy) to '%s'.\n", ea_endpoint->ep_serial, dest);
881 SCPY(e_ext.cfb, dest);
883 case INFO_DIVERSION_CFNR:
884 if ((rparam = routeparam(e_action, PARAM_DELAY)))
885 e_ext.cfnr_delay = rparam->integer_value;
886 printlog("%3d action CHANGE-FORWARD changing CFNR (no response) to '%s' with delay=%d.\n", ea_endpoint->ep_serial, dest, e_ext.cfnr_delay);
887 SCPY(e_ext.cfnr, dest);
889 case INFO_DIVERSION_CFP:
890 printlog("%3d action CHANGE-FORWARD changing CFP (parallel) to '%s'.\n", ea_endpoint->ep_serial, dest);
891 SCPY(e_ext.cfp, dest);
894 write_extension(&e_ext, e_terminal);
896 /* function (de)activated */
897 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
898 new_state(EPOINT_STATE_OUT_DISCONNECT);
900 set_tone(portlist,"activated");
902 set_tone(portlist,"deactivated");
906 /* process dialing redial
908 void EndpointAppPBX::action_init_redial_reply(void)
910 struct port_list *portlist = ea_endpoint->ep_portlist;
913 if (!e_ext.last_out[0])
915 printlog("%3d action REDIAL/REPLY no number available to dial.\n", ea_endpoint->ep_serial);
916 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): no stored last number.\n", ea_endpoint->ep_serial);
917 new_state(EPOINT_STATE_OUT_DISCONNECT);
918 message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
919 set_tone(portlist, "cause_3f");
924 /* process dialing redial
926 void EndpointAppPBX::_action_redial_reply(int in)
928 struct message *message;
930 struct route_param *rparam;
932 last = (in)?e_ext.last_in[0]:e_ext.last_out[0];
934 /* if no display is available */
935 if (!e_ext.display_menu)
937 if (ea_endpoint->ep_portlist->port_type!=PORT_TYPE_DSS1_NT_IN && ea_endpoint->ep_portlist->port_type!=PORT_TYPE_DSS1_NT_OUT)
940 /* if select is not given */
941 if (!(rparam = routeparam(e_action, PARAM_SELECT)))
945 if (e_extdialing[0]=='*' || e_extdialing[0]=='1')
947 /* find prev entry */
953 if (e_extdialing[0]=='#' || e_extdialing[0]=='3')
955 /* find next entry */
957 if (e_select >= MAX_REMEMBER)
960 if (e_ext.last_in[e_select][0] == '\0')
963 if (e_ext.last_out[e_select][0] == '\0')
968 last = (in)?e_ext.last_in[e_select]:e_ext.last_out[e_select];
969 if (e_extdialing[0]=='0' || e_extdialing[0]=='2')
972 printlog("%3d action REDIAL/REPLY dialing '%s'.\n", ea_endpoint->ep_serial, last);
973 SCPY(e_dialinginfo.number, last);
974 e_extdialing = e_dialinginfo.number;
979 e_extdialing[0] = '\0';
981 /* send display message to port */
982 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
983 if (!strncmp(last, "extern:", 7))
984 SPRINT(message->param.notifyinfo.display, "(%d) %s ext", e_select+1, last+7);
986 if (!strncmp(last, "intern:", 7))
987 SPRINT(message->param.notifyinfo.display, "(%d) %s int", e_select+1, last+7);
989 if (!strncmp(last, "chan:", 4))
990 SPRINT(message->param.notifyinfo.display, "(%d) %s chan", e_select+1, last+5);
992 if (!strncmp(last, "vbox:", 5))
993 SPRINT(message->param.notifyinfo.display, "(%d) %s vbox", e_select+1, last+5);
995 SPRINT(message->param.notifyinfo.display, "(%d) %s", e_select+1, (last[0])?last:"- empty -");
996 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s sending display:%s\n", ea_endpoint->ep_serial, e_terminal, message->param.notifyinfo.display);
997 message_put(message);
1001 /* process dialing redial
1003 void EndpointAppPBX::action_dialing_redial(void)
1005 _action_redial_reply(0);
1008 /* process dialing reply
1010 void EndpointAppPBX::action_dialing_reply(void)
1012 _action_redial_reply(1);
1016 /* dialing powerdialing delay
1018 void EndpointAppPBX::action_dialing_powerdial(void)
1020 struct port_list *portlist = ea_endpoint->ep_portlist;
1021 struct message *message;
1022 struct route_param *rparam;
1024 /* power dialing only possible if we have a last dialed number */
1025 if (!e_ext.last_out[0])
1027 printlog("%3d action POWERDIAL no number available to redial.\n", ea_endpoint->ep_serial);
1028 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): no stored last number.\n", ea_endpoint->ep_serial);
1029 new_state(EPOINT_STATE_OUT_DISCONNECT);
1030 message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
1031 set_tone(portlist, "cause_3f");
1036 if ((rparam = routeparam(e_action, PARAM_LIMIT)))
1038 e_powerlimit = rparam->integer_value;
1045 if ((rparam = routeparam(e_action, PARAM_DELAY)))
1047 e_powerdelay = rparam->integer_value;
1050 /* delay incomplete */
1051 if (!strchr(e_extdialing, '#'))
1053 *strchr(e_extdialing, '#') = '\0';
1054 e_powerdelay = e_extdialing[0]?atoi(e_extdialing): 0;
1057 if (e_powerdelay < 1)
1059 printlog("%3d action POWERDIAL to '%s' with delay=%d.\n", ea_endpoint->ep_serial, e_ext.last_out[0], (int)e_powerdelay);
1060 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): powerdialing to '%s' (delay=%d).\n", ea_endpoint->ep_serial, e_ext.last_out[0], (int)e_powerdelay);
1062 /* send connect to avoid overlap timeout */
1063 // new_state(EPOINT_STATE_CONNECT); connect may prevent further dialing
1066 memset(&e_connectinfo, 0, sizeof(e_connectinfo));
1067 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
1068 message_put(message);
1069 logmessage(message);
1072 SCPY(e_dialinginfo.number, e_ext.last_out[0]);
1073 e_powerdialing = -1; /* indicates the existence of powerdialing but no redial time given */
1082 void EndpointAppPBX::action_dialing_callback(void)
1084 struct port_list *portlist = ea_endpoint->ep_portlist;
1085 struct route_param *rparam;
1086 struct extension cbext;
1088 portlist = ea_endpoint->ep_portlist;
1090 /* check given extension */
1091 if (!(rparam = routeparam(e_action, PARAM_EXTENSION)))
1093 printlog("%3d action CALLBACK no extension was specified in routing.conf.\n", ea_endpoint->ep_serial);
1094 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): rejecting callback, because no extension was specified in routing.conf\n", ea_endpoint->ep_serial);
1097 new_state(EPOINT_STATE_OUT_DISCONNECT);
1098 message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
1099 set_tone(portlist, "cause_3f");
1101 e_cbcaller[0] = e_cbdialing[0] = '\0';
1105 /* if extension is given */
1106 SCPY(e_cbcaller, rparam->string_value);
1107 if (e_cbcaller[0] == '\0')
1109 printlog("%3d action CALLBACK extension specified in routing.conf is an empty string.\n", ea_endpoint->ep_serial);
1110 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): rejecting callback, because given extension is an empty string.\n", ea_endpoint->ep_serial);
1114 /* read callback extension */
1115 memset(&cbext, 0, sizeof(cbext));
1116 if (!read_extension(&cbext, e_cbcaller))
1118 printlog("%3d action CALLBACK extension '%s' specified in routing.conf doesn't exist.\n", ea_endpoint->ep_serial, e_cbcaller);
1119 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): rejecting callback, because given extension does not exist.\n", ea_endpoint->ep_serial);
1123 /* if password is not given */
1124 if (cbext.password[0] == '\0')
1126 printlog("%3d action CALLBACK extension '%s' has no password specified.\n", ea_endpoint->ep_serial, e_cbcaller);
1127 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): rejecting callback, because no password is available in given extension (%s).\n", ea_endpoint->ep_serial, e_cbcaller);
1131 /* callback only possible if callerid exists OR it is given */
1132 if ((rparam = routeparam(e_action, PARAM_CALLTO)))
1133 SCPY(e_cbto, rparam->string_value);
1136 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): callback to given number: '%s'\n", ea_endpoint->ep_serial, e_cbto);
1137 printlog("%3d action CALLBACK callback to given number: '%s'\n", ea_endpoint->ep_serial, e_cbto);
1138 SCPY(e_callerinfo.id, e_cbto);
1139 e_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1140 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1142 if (e_callerinfo.id[0]=='\0' || e_callerinfo.present==INFO_PRESENT_NOTAVAIL)
1144 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): rejecting callback, because no caller id is available\n", ea_endpoint->ep_serial);
1145 printlog("%3d action CALLBACK not possible because caller ID is not available.\n", ea_endpoint->ep_serial);
1149 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1154 * process hangup 'callback'
1156 void EndpointAppPBX::action_hangup_callback(void)
1158 struct route_param *rparam;
1162 delay = 2; /* default value */
1163 if ((rparam = routeparam(e_action, PARAM_DELAY)))
1164 if (rparam->integer_value>0)
1165 delay = rparam->integer_value;
1167 /* dialing after callback */
1168 if ((rparam = routeparam(e_action, PARAM_PREFIX)))
1169 SCPY(e_cbdialing, rparam->string_value);
1171 SCPY(e_cbdialing, e_extdialing);
1173 printlog("%3d action CALLBACK extension=%s callerid='%s' delay='%d' dialing after callback='%s' .\n", ea_endpoint->ep_serial, e_cbcaller, e_callerinfo.id, delay, e_cbdialing);
1174 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): caller '%s', callerid '%s', dialing '%s', delay %d\n", ea_endpoint->ep_serial, e_cbcaller, e_callerinfo.id, e_cbdialing, delay);
1176 /* set time to callback */
1177 e_callback = now_d + delay;
1182 * dialing action abbreviation
1184 void EndpointAppPBX::action_dialing_abbrev(void)
1186 struct port_list *portlist = ea_endpoint->ep_portlist;
1187 char *abbrev, *phone, *name;
1190 portlist = ea_endpoint->ep_portlist;
1192 /* abbrev dialing is only possible if we have a caller defined */
1195 printlog("%3d action ABBREVIATION only possible for internal callers.\n", ea_endpoint->ep_serial);
1196 new_state(EPOINT_STATE_OUT_DISCONNECT);
1197 message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
1198 set_tone(portlist, "cause_3f");
1202 /* check abbreviation */
1203 abbrev = e_extdialing;
1206 result = parse_phonebook(e_terminal, &abbrev, &phone, &name);
1209 printlog("%3d action ABBREVIATION '%s' not found.\n", ea_endpoint->ep_serial, abbrev);
1210 new_state(EPOINT_STATE_OUT_DISCONNECT);
1211 message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, "");
1212 set_tone(portlist, "cause_01");
1215 if (result == -1) /* may match if more digits are dialed */
1220 /* dial abbreviation */
1221 printlog("%3d action ABBREVIATION mapping '%s' to '%s' (%s), dialing...\n", ea_endpoint->ep_serial, abbrev, phone, name?name:"unknown");
1222 SCPY(e_dialinginfo.number, phone);
1223 e_extdialing = e_dialinginfo.number;
1229 /* process dialing 'test'
1231 void EndpointAppPBX::action_dialing_test(void)
1235 struct port_list *portlist = ea_endpoint->ep_portlist;
1236 struct message *message;
1238 char testcode[32] = "";
1239 struct route_param *rparam;
1241 /* given testcode */
1242 if ((rparam = routeparam(e_action, PARAM_PREFIX)))
1243 SCPY(testcode, rparam->string_value);
1244 SCAT(testcode, e_extdialing);
1249 printlog("%3d action TESTMODE executing 'proceeding' test.\n", ea_endpoint->ep_serial);
1250 new_state(EPOINT_STATE_IN_PROCEEDING);
1251 set_tone(portlist, "proceeding");
1252 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
1253 message_put(message);
1254 logmessage(message);
1258 printlog("%3d action TESTMODE executing 'alerting' test.\n", ea_endpoint->ep_serial);
1259 new_state(EPOINT_STATE_IN_ALERTING);
1260 set_tone(portlist, "ringpbx");
1261 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
1262 message_put(message);
1263 logmessage(message);
1267 printlog("%3d action TESTMODE executing 'echo connect' test.\n", ea_endpoint->ep_serial);
1268 new_state(EPOINT_STATE_CONNECT);
1271 set_tone(portlist, NULL);
1272 memset(&e_connectinfo, 0, sizeof(e_connectinfo));
1273 SCPY(e_connectinfo.id, e_callerinfo.id);
1274 SCPY(e_connectinfo.intern, e_callerinfo.intern);
1275 SCPY(e_connectinfo.voip, e_callerinfo.voip);
1276 e_connectinfo.itype = e_callerinfo.itype;
1277 e_connectinfo.ntype = e_callerinfo.ntype;
1278 e_connectinfo.present = e_callerinfo.present;
1279 e_connectinfo.screen = e_callerinfo.screen;
1280 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
1281 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
1282 /* handle restricted caller ids */
1283 apply_callerid_restriction(e_ext.anon_ignore, portlist->port_type, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name);
1284 /* display callerid if desired for extension */
1285 SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype, message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name));
1286 message_put(message);
1287 logmessage(message);
1289 port = find_port_id(portlist->port_id);
1292 port->set_echotest(1);
1297 printlog("%3d action TESTMODE executing 'tone connect' test.\n", ea_endpoint->ep_serial);
1298 new_state(EPOINT_STATE_CONNECT);
1301 memset(&e_connectinfo, 0, sizeof(e_connectinfo));
1302 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
1303 message_put(message);
1304 logmessage(message);
1305 set_tone(portlist, "test");
1309 printlog("%3d action TESTMODE executing 'hold music' test.\n", ea_endpoint->ep_serial);
1310 new_state(EPOINT_STATE_CONNECT);
1313 memset(&e_connectinfo, 0, sizeof(e_connectinfo));
1314 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
1315 message_put(message);
1316 logmessage(message);
1317 set_tone(portlist, "hold");
1321 if (strlen(testcode) < 4)
1324 cause = atoi(testcode+1);
1327 printlog("%3d action TESTMODE executing 'announcement' test with cause %d.\n", ea_endpoint->ep_serial, cause);
1328 new_state(EPOINT_STATE_CONNECT);
1331 SPRINT(causestr,"cause_%02x",cause);
1332 memset(&e_connectinfo, 0, sizeof(e_connectinfo));
1333 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
1334 message_put(message);
1335 logmessage(message);
1336 set_tone(portlist, causestr);
1340 if (strlen(testcode) < 4)
1343 cause = atoi(testcode+1);
1346 printlog("%3d action TESTMODE executing 'disconnect' test with cause %d.\n", ea_endpoint->ep_serial, cause);
1347 new_state(EPOINT_STATE_OUT_DISCONNECT);
1348 SPRINT(causestr,"cause_%02x",cause);
1349 message_disconnect_port(portlist, cause, LOCATION_PRIVATE_LOCAL, "");
1350 set_tone(portlist, causestr);
1353 case '8': /* release */
1354 printlog("%3d action TESTMODE executing 'release' test.\n", ea_endpoint->ep_serial);
1355 new_state(EPOINT_STATE_OUT_DISCONNECT);
1356 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1357 set_tone(portlist, "release");
1360 case '9': /* text callerid test */
1361 printlog("%3d action TESTMODE executing 'caller id' test.\n", ea_endpoint->ep_serial);
1362 new_state(EPOINT_STATE_CONNECT);
1365 memset(&e_connectinfo, 0, sizeof(e_connectinfo));
1366 SCPY(e_connectinfo.id, "12345678");
1367 SCPY(e_connectinfo.name, "Welcome to Linux");
1368 SCPY(e_connectinfo.display, "Welcome to Linux");
1369 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
1370 e_connectinfo.present = INFO_PRESENT_ALLOWED;
1371 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
1372 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(message->param.connectinfo));
1373 message_put(message);
1374 logmessage(message);
1375 set_tone(portlist, "hold");
1381 /* process init play
1383 void EndpointAppPBX::action_init_play(void)
1385 struct route_param *rparam;
1386 struct port_list *portlist = ea_endpoint->ep_portlist;
1388 /* check given sample */
1389 if (!(rparam = routeparam(e_action, PARAM_SAMPLE)))
1391 printlog("%3d action PLAY no sample given.\n", ea_endpoint->ep_serial);
1392 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): cannot play, because no sample has been specified\n", ea_endpoint->ep_serial);
1395 new_state(EPOINT_STATE_OUT_DISCONNECT);
1396 message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
1397 set_tone(portlist, "cause_3f");
1402 /* if sample is given */
1403 if (rparam->string_value[0] == '\0')
1405 printlog("%3d action PLAY sample name with empty string given.\n", ea_endpoint->ep_serial);
1406 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): cannot play, because given sample is an empty string.\n", ea_endpoint->ep_serial);
1413 set_tone(ea_endpoint->ep_portlist, rparam->string_value);
1418 * action_*_vbox_play is implemented in "action_vbox.cpp"
1423 * process dialing of calculator
1425 void EndpointAppPBX::action_dialing_calculator(void)
1427 struct port_list *portlist = ea_endpoint->ep_portlist;
1428 struct message *message;
1429 double value1, value2, v, sign1;
1430 int komma1, komma2, k, state, mode, first;
1433 portlist = ea_endpoint->ep_portlist;
1435 /* remove error message */
1436 if (!strncmp(e_extdialing, "Error", 5))
1438 UCPY(e_extdialing, e_extdialing+5);
1440 if (!strncmp(e_extdialing, "inf", 3))
1442 UCPY(e_extdialing, e_extdialing+3);
1444 if (!strncmp(e_extdialing, "-inf", 4))
1446 UCPY(e_extdialing, e_extdialing+4);
1449 /* process dialing */
1462 if (*p>='0' && *p<='9')
1470 if ((p[-1]<'0' || p[-1]>'0') && p[-1]!='.')
1479 case 0: /* first number */
1482 value1 = value1*10 + (*p-'0');
1492 case 1: /* second number */
1495 value2 = value2*10 + (*p-'0');
1512 UCPY(e_extdialing, "Error");
1515 /* if there is a multiplication, we change to / */
1524 /* if there is a division, we change to + */
1533 /* if there is a addition, we change to - */
1542 /* if there is a substraction and a comma, we change to * */
1543 if (p[-1]=='-' && komma1)
1551 /* if there is a substraction and no comma and the first or second value, we change to , */
1560 /* if there is a komma and we are at the first value, we change to * */
1561 if (p[-1]=='.' && state==0)
1570 /* if there is a komma and we are at the second value, we display error */
1571 if (komma2 && state==1)
1573 UCPY(e_extdialing, "Error");
1576 /* if we are at state 1, we write a comma */
1583 /* we assume multiplication */
1590 /* if just a number is displayed, the input is cleared */
1593 *e_extdialing = '\0';
1596 /* calculate the result */
1599 case 0: /* multiply */
1600 UNPRINT(e_extdialing, sizeof(e_dialinginfo.number)-strlen(e_dialinginfo.number), "%.8f", sign1*value1*value2);
1602 case 1: /* divide */
1603 UNPRINT(e_extdialing, sizeof(e_dialinginfo.number)-strlen(e_dialinginfo.number), "%.8f", sign1*value1/value2);
1606 UNPRINT(e_extdialing, sizeof(e_dialinginfo.number)-strlen(e_dialinginfo.number), "%.8f", sign1*value1+value2);
1608 case 3: /* substract */
1609 UNPRINT(e_extdialing, sizeof(e_dialinginfo.number)-strlen(e_dialinginfo.number), "%.8f", sign1*value1-value2);
1612 e_dialinginfo.number[sizeof(e_dialinginfo.number)-1] = '\0';
1613 if (strchr(e_extdialing, '.')) /* remove zeroes */
1615 while (e_extdialing[strlen(e_extdialing)-1] == '0')
1616 e_extdialing[strlen(e_extdialing)-1] = '\0';
1617 if (e_extdialing[strlen(e_extdialing)-1] == '.')
1618 e_extdialing[strlen(e_extdialing)-1] = '\0'; /* and remove dot */
1620 p = strchr(e_extdialing,'\0')-1;
1653 UCPY(e_extdialing, "Error");
1662 /* display dialing */
1663 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
1664 SPRINT(message->param.notifyinfo.display, ">%s", e_extdialing);
1665 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s displaying interpreted dialing '%s' internal values: %f %f\n", ea_endpoint->ep_serial, e_terminal, e_extdialing, value1, value2);
1666 message_put(message);
1667 logmessage(message);
1672 * process dialing of timer
1674 void EndpointAppPBX::action_dialing_timer(void)
1680 * process 'goto' or 'menu'
1682 void EndpointAppPBX::_action_goto_menu(int mode)
1684 struct port_list *portlist = ea_endpoint->ep_portlist;
1685 struct route_param *rparam;
1687 /* check given ruleset */
1688 if (!(rparam = routeparam(e_action, PARAM_RULESET)))
1691 printlog("%3d action GOTO/MENU no ruleset ginven in options.conf\n", ea_endpoint->ep_serial);
1692 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): no ruleset was secified for action '%s' in routing.conf\n", ea_endpoint->ep_serial, (mode)?"menu":"goto");
1695 new_state(EPOINT_STATE_OUT_DISCONNECT);
1696 message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
1697 set_tone(portlist, "cause_3f");
1701 if (rparam->string_value[0] == '\0')
1703 e_ruleset = getrulesetbyname(rparam->string_value);
1706 printlog("%3d action GOTO/MENU given ruleset '%s' not found in options.conf\n", ea_endpoint->ep_serial, rparam->string_value);
1707 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): given ruleset '%s' for action '%s' was not found in routing.conf\n", ea_endpoint->ep_serial, rparam->string_value, (mode)?"menu":"goto");
1710 printlog("%3d action GOTO/MENU changing to ruleset '%s'\n", ea_endpoint->ep_serial, rparam->string_value);
1712 /* if the 'menu' was selected, we will flush all digits */
1715 //SCPY(e_dialinginfo.number, e_extdialing);
1716 e_dialinginfo.number[0] = 0;
1717 e_extdialing = e_dialinginfo.number;
1723 if ((rparam = routeparam(e_action, PARAM_SAMPLE)))
1725 printlog("%3d action GOTO/MENU start playing sample '%s'\n", ea_endpoint->ep_serial, rparam->string_value);
1726 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): playing sample '%s'\n", ea_endpoint->ep_serial, rparam->string_value);
1727 set_tone(ea_endpoint->ep_portlist, rparam->string_value);
1730 /* do dialing with new ruleset */
1735 /* process dialing goto
1737 void EndpointAppPBX::action_dialing_goto(void)
1739 _action_goto_menu(0);
1742 /* process dialing menu
1744 void EndpointAppPBX::action_dialing_menu(void)
1746 _action_goto_menu(1);
1751 * process dialing disconnect
1753 void EndpointAppPBX::action_dialing_disconnect(void)
1755 struct route_param *rparam;
1756 struct port_list *portlist = ea_endpoint->ep_portlist;
1757 struct message *message;
1758 int cause = CAUSE_NORMAL; /* normal call clearing */
1759 int location = LOCATION_PRIVATE_LOCAL;
1760 char cause_string[256] = "", display[84] = "";
1762 /* check cause parameter */
1763 if ((rparam = routeparam(e_action, PARAM_CAUSE)))
1765 cause = rparam->integer_value;
1766 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'cause' is given: %d\n", ea_endpoint->ep_serial, cause);
1768 if ((rparam = routeparam(e_action, PARAM_LOCATION)))
1770 location = rparam->integer_value;
1771 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'location' is given: %d\n", ea_endpoint->ep_serial, location);
1775 /* use cause as sample, if not given later */
1776 SPRINT(cause_string, "cause_%02x", cause);
1778 /* check sample parameter */
1779 if ((rparam = routeparam(e_action, PARAM_SAMPLE)))
1781 SCPY(cause_string, rparam->string_value);
1782 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'sample' is given: %s\n", ea_endpoint->ep_serial, cause_string);
1786 if ((rparam = routeparam(e_action, PARAM_DISPLAY)))
1788 SCPY(display, rparam->string_value);
1789 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'display' is given: %s\n", ea_endpoint->ep_serial, display);
1792 /* disconnect only if connect parameter is not given */
1793 printlog("%3d action DISCONNECT with cause %d, location %d, sample '%s', display '%s'\n", ea_endpoint->ep_serial, cause, location, cause_string, display);
1794 new_state(EPOINT_STATE_OUT_DISCONNECT);
1795 set_tone(portlist, cause_string);
1796 if (!(rparam = routeparam(e_action, PARAM_CONNECT)))
1798 message_disconnect_port(portlist, cause, location, display);
1801 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
1802 SCPY(message->param.notifyinfo.display, display);
1803 message_put(message);
1804 logmessage(message);
1811 * process dialing help
1813 void EndpointAppPBX::action_dialing_help(void)
1815 /* show all things that would match */
1817 struct numbering *numbering = numbering_int;
1818 char dialing[sizeof(e_dialinginfo.number)];
1820 struct message *message;
1821 struct route_param *rparam;
1823 /* in case we have no menu (this should never happen) */
1828 if (strchr(e_dialinginfo.number,'*'))
1831 e_dialinginfo.number[0] = '\0';
1833 if (strchr(e_dialinginfo.number,'#'))
1836 e_dialinginfo.number[0] = '\0';
1839 /* get position in menu */
1842 /* get last menu position */
1844 while(numbering->next)
1847 numbering = numbering->next;
1851 /* get menu position */
1855 numbering = numbering->next;
1859 numbering = numbering_int;
1866 /* if we dial something else we need to add the prefix and change the action */
1867 if (e_dialinginfo.number[0])
1869 e_action = NUMB_ACTION_NONE;
1870 SCPY(dialing, numbering->prefix);
1871 //we ignore the first digit after selecting
1872 //SCAT(dialing, e_dialinginfo.number);
1873 SCPY(e_dialinginfo.number, dialing);
1874 e_extdialing = e_dialinginfo.number+strlen(numbering->prefix);
1875 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s selected a new menu '%s' dialing: %s\n", ea_endpoint->ep_serial, e_terminal, numb_actions[numbering->action], e_dialinginfo.number);
1881 /* send display message to port */
1882 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
1883 SPRINT(message->param.notifyinfo.display, ">%s %s%s%s", numbering->prefix, numb_actions[numbering->action], (numbering->param[0])?" ":"", numbering->param);
1884 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s selected a new menu '%s' sending display:%s\n", ea_endpoint->ep_serial, e_terminal, numb_actions[numbering->action], message->param.notifyinfo.display);
1885 message_put(message);
1886 logmessage(message);
1892 * process dialing deflect
1894 void EndpointAppPBX::action_dialing_deflect(void)
1900 * process dialing setforward
1902 void EndpointAppPBX::action_dialing_setforward(void)
1908 * process hangup 'execute'
1910 void EndpointAppPBX::action_hangup_execute(void)
1912 struct route_param *rparam;
1913 char *command = "", isdn_port[10];
1914 char *argv[8+1]; /* check also number of args below */
1917 /* get script / command */
1918 if ((rparam = routeparam(e_action, PARAM_EXECUTE)))
1919 command = rparam->string_value;
1920 if (command[0] == '\0')
1922 printlog("%3d action EXECUTE no 'execute' parameter given at routing.conf.\n", ea_endpoint->ep_serial);
1923 PERROR("EPOINT(%d): terminal %s: NO PARAMETER GIVEN for 'execute' action. see routing.conf\n", ea_endpoint->ep_serial, e_terminal);
1926 printlog("%3d action EXECUTE command='%s'\n", ea_endpoint->ep_serial, command);
1927 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: executing '%s'.\n", ea_endpoint->ep_serial, e_terminal, command);
1930 while(strchr(argv[0], '/'))
1931 argv[0] = strchr(argv[0], '/')+1;
1932 if ((rparam = routeparam(e_action, PARAM_PARAM)))
1934 argv[1] = rparam->string_value;
1937 argv[1+i] = e_extdialing;
1938 argv[2+i] = numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype);
1939 argv[3+i] = e_callerinfo.intern;
1940 argv[4+i] = e_callerinfo.voip;
1941 argv[5+i] = e_callerinfo.name;
1942 SPRINT(isdn_port, "%d", e_callerinfo.isdn_port);
1943 argv[6+i] = isdn_port;
1944 argv[7+i] = NULL; /* check also number of args above */
1945 execve("/bin/sh", argv, environ);
1950 * process hangup 'file'
1952 void EndpointAppPBX::action_hangup_file(void)
1954 struct route_param *rparam;
1955 char *file, *content, *mode;
1958 /* get file / content */
1959 if (!(rparam = routeparam(e_action, PARAM_FILE)))
1960 file = rparam->string_value;
1963 if (!(rparam = routeparam(e_action, PARAM_CONTENT)))
1964 content = rparam->string_value;
1966 content = e_extdialing;
1967 if (!(rparam = routeparam(e_action, PARAM_APPEND)))
1971 if (file[0] == '\0')
1973 printlog("%3d action FILE no filename given.\n", ea_endpoint->ep_serial);
1974 PERROR("EPOINT(%d): terminal %s: NO FILENAME GIVEN for 'file' action. see routing.conf\n", ea_endpoint->ep_serial, e_terminal);
1977 if (!(fp = fopen(file, mode)))
1979 printlog("%3d action FILE file '%s' cannot be opened. (errno = %d)\n", ea_endpoint->ep_serial, file, errno);
1980 PERROR("EPOINT(%d): terminal %s: given file '%s' cannot be opened. see routing.conf\n", ea_endpoint->ep_serial, e_terminal, file);
1983 printlog("%3d action FILE file='%s' content='%s'\n", ea_endpoint->ep_serial, file, content);
1984 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: writing file '%s' with content '%s'.\n", ea_endpoint->ep_serial, e_terminal, file, content);
1985 fprintf(fp, "%s\n", content);
1991 * process init 'pick'
1993 void EndpointAppPBX::action_init_pick(void)
1995 struct route_param *rparam;
1996 char *extensions = NULL;
1998 if ((rparam = routeparam(e_action, PARAM_EXTENSIONS)))
1999 extensions = rparam->string_value;
2001 printlog("%3d action PICK\n", ea_endpoint->ep_serial);
2002 pick_call(extensions);
2007 * process dialing 'password'
2009 void EndpointAppPBX::action_dialing_password(void)
2011 struct port_list *portlist = ea_endpoint->ep_portlist;
2013 /* prompt for password */
2014 if (e_extdialing[0] == '\0')
2016 /* give password tone */
2017 set_tone(portlist, "password");
2019 if (e_extdialing[1] == '\0')
2021 /* give password tone */
2022 set_tone(portlist, "dialing");
2025 /* wait until all digits are dialed */
2026 if (strlen(e_ext.password) != strlen(e_extdialing))
2027 return; /* more digits needed */
2029 /* check the password */
2030 if (e_ext.password[0]=='\0' || (strlen(e_ext.password)==strlen(e_extdialing) && !!strcmp(e_ext.password,e_extdialing)))
2032 printlog("%3d action PASSWORD WRITE password wrong\n", ea_endpoint->ep_serial);
2033 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): password wrong %s\n", ea_endpoint->ep_serial, e_extdialing);
2034 e_connectedmode = 0;
2036 new_state(EPOINT_STATE_OUT_DISCONNECT);
2037 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
2038 set_tone(portlist, "cause_10");
2042 /* write caller id if ACTION_PASSWORD_WRITE was selected */
2044 if (e_action->index == ACTION_PASSWORD_WRITE)
2046 append_callbackauth(e_terminal, &e_callbackinfo);
2047 printlog("%3d action PASSWORD WRITE password written\n", ea_endpoint->ep_serial);
2050 /* make call state */
2051 new_state(EPOINT_STATE_IN_OVERLAP);
2052 e_ruleset = ruleset_main;
2054 e_rule = e_ruleset->rule_first;
2056 e_dialinginfo.number[0] = '\0';
2057 e_extdialing = e_dialinginfo.number;
2058 set_tone(portlist, "dialpbx");
2061 void EndpointAppPBX::action_dialing_password_wr(void)
2063 action_dialing_password();
2067 /* general process dialing of incoming call
2068 * depending on the detected prefix, subfunctions above (action_*) will be
2071 void EndpointAppPBX::process_dialing(void)
2073 struct port_list *portlist = ea_endpoint->ep_portlist;
2074 struct message *message;
2075 struct route_param *rparam;
2077 //#warning Due to HANG-BUG somewhere here, I added some HANG-BUG-DEBUGGING output that cannot be disabled. after bug has been found, this will be removed.
2078 //PDEBUG(~0, "HANG-BUG-DEBUGGING: entered porcess_dialing\n");
2079 portlist = ea_endpoint->ep_portlist;
2080 /* check if we have a port instance linked to our epoint */
2084 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): note: dialing call requires exactly one port object to process dialing. this case could happen due to a parked call. we end dialing here.\n", ea_endpoint->ep_serial, e_terminal);
2085 e_action_timeout = 0;
2086 e_match_timeout = 0;
2091 goto portlist_error;
2094 /* check nesting levels */
2095 if (++e_rule_nesting > RULE_NESTING)
2097 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): rules are nesting too deep. (%d levels) check for infinite loops in routing.conf\n", ea_endpoint->ep_serial, e_rule_nesting);
2098 new_state(EPOINT_STATE_OUT_DISCONNECT);
2099 message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
2100 set_tone(portlist, "cause_3f");
2101 e_action_timeout = 0;
2102 e_match_timeout = 0;
2106 //PDEBUG(~0, "HANG-BUG-DEBUGGING: before action-timeout processing\n");
2107 /* process timeout */
2108 if (e_action_timeout)
2110 e_action_timeout = 0;
2111 if (e_state == EPOINT_STATE_CONNECT)
2113 PDEBUG(DEBUG_ROUTE|DEBUG_EPOINT, "EPOINT(%d): action timed out, but we already have connected, so we stop timer and continue.\n", ea_endpoint->ep_serial);
2116 if (e_action->index == ACTION_DISCONNECT
2117 || e_state == EPOINT_STATE_OUT_DISCONNECT)
2119 /* release after disconnect */
2120 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2123 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, 0);
2124 e_action = e_action->next;
2127 /* nothing more, so we release */
2128 PDEBUG(DEBUG_ROUTE|DEBUG_EPOINT, "EPOINT(%d): action timed out, and we have no next action, so we disconnect.\n", ea_endpoint->ep_serial);
2129 new_state(EPOINT_STATE_OUT_DISCONNECT);
2130 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
2131 set_tone(portlist, "cause_3f");
2134 PDEBUG(DEBUG_ROUTE|DEBUG_EPOINT, "EPOINT(%d): continueing with action '%s'.\n", ea_endpoint->ep_serial, action_defs[e_action->index].name);
2135 goto action_timeout;
2138 //PDEBUG(~0, "HANG-BUG-DEBUGGING: before setup/overlap state checking\n");
2139 if (e_state!=EPOINT_STATE_IN_SETUP
2140 && e_state!=EPOINT_STATE_IN_OVERLAP)
2142 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): we are not in incomming setup/overlap state, so we ignore init/dialing process.\n", ea_endpoint->ep_serial, e_rule_nesting);
2143 e_match_timeout = 0;
2148 /* check if we do menu selection */
2149 if (e_action==NUMB_ACTION_NONE && (e_dialinginfo.number[0]=='*' || e_dialinginfo.number[0]=='#'))
2150 /* do menu selection */
2151 if (e_ext.display_menu)
2153 if (portlist->port_type==PORT_TYPE_DSS1_NT_IN || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* only if the dialing terminal is an isdn telephone connected to an internal port */
2155 e_dialinginfo.number[0] = '\0';
2156 e_action = NUMB_ACTION_MENU;
2159 e_match_timeout = 0;
2162 /* invalid dialing */
2163 message_disconnect_port(portlist, CAUSE_INCALID, LOCATION_PRIVATE_LOCAL, "");
2164 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
2165 message->param.disconnectinfo.cause = CAUSE_INVALID;
2166 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2169 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
2170 SCPY(message->param.notifyinfo.display,get_isdn_cause(LOCATION_PRIVATE_LOCAL, epoint->e_ext.display_cause, param->disconnectinfo.location, param->disconnectinfo.cause));
2172 message_put(message);
2173 logmessage(message);
2175 new_state(EPOINT_STATE_OUT_DISCONNECT);
2176 set_tone(portlist,"cause_1c");
2177 e_match_timeout = 0;
2182 //PDEBUG(~0, "HANG-BUG-DEBUGGING: before e_action==NULL\n");
2183 /* if no action yet, we will call try to find a matching rule */
2186 /* be sure that all selectors are initialized */
2189 /* check for external call */
2190 if (!strncmp(e_dialinginfo.number, "extern:", 7))
2192 e_extdialing = e_dialinginfo.number+7;
2193 e_action = &action_external;
2194 goto process_action;
2196 /* check for internal call */
2197 if (!strncmp(e_dialinginfo.number, "intern:", 7))
2199 e_extdialing = e_dialinginfo.number+7;
2200 e_action = &action_internal;
2201 goto process_action;
2203 /* check for chan call */
2204 if (!strncmp(e_dialinginfo.number, "chan:", 5))
2206 e_extdialing = e_dialinginfo.number+4;
2207 e_action = &action_chan;
2208 goto process_action;
2210 /* check for vbox call */
2211 if (!strncmp(e_dialinginfo.number, "vbox:", 5))
2213 e_extdialing = e_dialinginfo.number+5;
2214 e_action = &action_vbox;
2215 goto process_action;
2218 if (e_match_timeout && now_d>=e_match_timeout)
2220 /* return timeout rule */
2221 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal '%s' dialing: '%s', timeout in ruleset '%s'\n", ea_endpoint->ep_serial, e_terminal, e_dialinginfo.number, e_ruleset->name);
2222 e_match_timeout = 0;
2223 e_action = e_match_to_action;
2224 e_extdialing = e_match_to_extdialing;
2225 printlog("%3d routing TIMEOUT processing action '%s' (line %d)\n", ea_endpoint->ep_serial, action_defs[e_action->index].name, e_action->line);
2229 //PDEBUG(~0, "HANG-BUG-DEBUGGING: before routing\n");
2230 /* check for matching rule */
2231 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal '%s' dialing: '%s', checking matching rule of ruleset '%s'\n", ea_endpoint->ep_serial, e_terminal, e_dialinginfo.number, e_ruleset->name);
2234 e_action = route(e_ruleset);
2236 printlog("%3d routing MATCH processing action '%s' (line %d)\n", ea_endpoint->ep_serial, action_defs[e_action->index].name, e_action->line);
2239 e_action = &action_disconnect;
2241 printlog("%3d routing NO MAIN RULESET, DISCONNECTING! '%s'\n", ea_endpoint->ep_serial, action_defs[e_action->index].name);
2243 //PDEBUG(~0, "HANG-BUG-DEBUGGING: after routing\n");
2247 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): no rule within the current ruleset matches yet.\n", ea_endpoint->ep_serial, e_terminal);
2252 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): a rule with action '%s' matches.\n", ea_endpoint->ep_serial, action_defs[e_action->index].name);
2257 e_action_timeout = 0;
2258 if (e_action->timeout)
2260 e_action_timeout = now_d + e_action->timeout;
2261 PDEBUG(DEBUG_ROUTE|DEBUG_EPOINT, "EPOINT(%d): action has a timeout of %d secods.\n", ea_endpoint->ep_serial, e_action->timeout);
2265 /* check param proceeding / alerting / connect */
2266 if ((rparam = routeparam(e_action, PARAM_CONNECT)))
2268 /* NOTE: we may not change our state to connect, because dialing will then not possible */
2270 memset(&e_connectinfo, 0, sizeof(e_connectinfo));
2271 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2272 message_put(message);
2273 logmessage(message);
2275 if ((rparam = routeparam(e_action, PARAM_ALERTING)))
2277 /* NOTE: we may not change our state to alerting, because dialing will then not possible */
2278 memset(&e_connectinfo, 0, sizeof(e_connectinfo));
2279 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2280 message_put(message);
2281 logmessage(message);
2283 if ((rparam = routeparam(e_action, PARAM_PROCEEDING)))
2285 /* NOTE: we may not change our state to proceeding, because dialing will then not possible */
2286 memset(&e_connectinfo, 0, sizeof(e_connectinfo));
2287 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2288 message_put(message);
2289 logmessage(message);
2292 if (action_defs[e_action->index].init_func)
2294 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: current action '%s' has a init function, so we call it...\n", ea_endpoint->ep_serial, e_terminal, action_defs[e_action->index].name);
2295 (this->*(action_defs[e_action->index].init_func))();
2297 if (e_state!=EPOINT_STATE_IN_SETUP
2298 && e_state!=EPOINT_STATE_IN_OVERLAP)
2300 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): AFTER init process: we are not in incomming setup/overlap state anymore, so we ignore further dialing process.\n", ea_endpoint->ep_serial, e_rule_nesting);
2301 goto display_action;
2305 /* show what we are doing */
2306 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal '%s' action: %s (dialing '%s')\n", ea_endpoint->ep_serial, e_terminal, action_defs[e_action->index].name, e_extdialing);
2307 /* go to action's dialing function */
2308 if (action_defs[e_action->index].dialing_func)
2310 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: current action '%s' has a dialing function, so we call it...\n", ea_endpoint->ep_serial, e_terminal, action_defs[e_action->index].name);
2311 (this->*(action_defs[e_action->index].dialing_func))();
2314 /* display selected dialing action if enabled and still in setup state */
2318 if (e_action->index==ACTION_MENU
2319 || e_action->index==ACTION_REDIAL
2320 || e_action->index==ACTION_REPLY
2321 || e_action->index==ACTION_TIMER
2322 || e_action->index==ACTION_CALCULATOR
2323 || e_action->index==ACTION_TEST)
2327 if (!e_ext.display_dialing)
2329 if (e_state==EPOINT_STATE_IN_OVERLAP || e_state==EPOINT_STATE_IN_PROCEEDING || e_state==EPOINT_STATE_IN_ALERTING || e_state==EPOINT_STATE_CONNECT/* || e_state==EPOINT_STATE_IN_DISCONNECT || e_state==EPOINT_STATE_OUT_DISCONNECT*/)
2330 if (portlist->port_type==PORT_TYPE_DSS1_NT_IN || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* only if the dialing terminal is an isdn telephone connected to an internal port */
2332 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
2336 SPRINT(message->param.notifyinfo.display, "> %s", e_dialinginfo.number);
2339 SPRINT(message->param.notifyinfo.display, "%s%s%s", action_defs[e_action->index].name, (e_extdialing[0])?" ":"", e_extdialing);
2342 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s displaying interpreted dialing '%s'\n", ea_endpoint->ep_serial, e_terminal, message->param.notifyinfo.display);
2343 message_put(message);
2344 logmessage(message);
2353 /* some services store information after hangup */
2354 void EndpointAppPBX::process_hangup(int cause, int location)
2356 char callertext[256], dialingtext[256];
2357 int writeext = 0, i;
2359 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal '%s'\n", ea_endpoint->ep_serial, e_terminal);
2362 if (read_extension(&e_ext, e_terminal))
2372 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): writing connect from %s to %s into logfile of %s\n", ea_endpoint->ep_serial, e_callerinfo.id, e_dialinginfo.number, e_terminal);
2373 switch(e_dialinginfo.itype)
2375 case INFO_ITYPE_CHAN:
2376 SPRINT(dialingtext, "chan:%s", e_dialinginfo.number);
2378 case INFO_ITYPE_INTERN:
2379 SPRINT(dialingtext, "intern:%s", e_dialinginfo.number);
2381 case INFO_ITYPE_VBOX:
2382 SPRINT(dialingtext, "vbox:%s", e_dialinginfo.number);
2385 SPRINT(dialingtext, "%s", e_dialinginfo.number);
2388 if (e_callerinfo.id[0])
2389 SPRINT(callertext, "%s", numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype));
2391 SPRINT(callertext, "unknown");
2392 /* allpy restriction */
2393 if (!e_ext.anon_ignore && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
2394 SPRINT(callertext, "anonymous");
2395 if (e_callerinfo.intern[0]) /* add intern if present */
2396 UNPRINT(strchr(callertext,'\0'), sizeof(callertext)-1+strlen(callertext), " (intern %s)", e_callerinfo.intern);
2397 if (e_callerinfo.voip[0]) /* add voip if present */
2398 UNPRINT(strchr(callertext,'\0'), sizeof(callertext)-1+strlen(callertext), " (voip %s)", e_callerinfo.voip);
2399 write_log(e_terminal, callertext, dialingtext, e_start, e_stop, 0, cause, location);
2401 /* store last received call for reply-list */
2402 if (e_callerinfo.id[0] || e_callerinfo.intern[0])
2403 if (e_ext.anon_ignore || e_callerinfo.present!=INFO_PRESENT_RESTRICTED)
2405 if (e_callerinfo.intern[0])
2406 SPRINT(callertext, "intern:%s", e_callerinfo.intern);
2408 SPRINT(callertext, "extern:%s", numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype));
2409 if (!!strcmp(callertext, e_ext.last_in[0]))
2414 UCPY(e_ext.last_in[i], e_ext.last_in[i-1]);
2417 SCPY(e_ext.last_in[0], callertext);
2418 writeext |= 1; /* store extension later */
2419 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: storing last received caller id '%s'.\n", ea_endpoint->ep_serial, e_terminal, e_ext.last_in[0]);
2421 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last received id '%s' because it is identical with the last one.\n", ea_endpoint->ep_serial, e_terminal, callertext);
2425 /* write extension if needed */
2426 if (writeext == 0x11)
2427 write_extension(&e_ext, e_terminal);
2431 if (action_defs[e_action->index].hangup_func)
2433 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: current action '%s' has a hangup function, so we call it...\n", ea_endpoint->ep_serial, e_terminal, action_defs[e_action->index].name);
2434 (this->*(action_defs[e_action->index].hangup_func))();