1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 #include <sys/types.h>
24 class EndpointAppPBX *apppbx_first = NULL;
27 * EndpointAppPBX constructor
29 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint) : EndpointApp(epoint)
31 class EndpointAppPBX **apppointer;
33 /* add application to chain */
35 apppointer = &apppbx_first;
37 apppointer = &((*apppointer)->next);
41 memset(&e_ext, 0, sizeof(struct extension));
42 e_ext.rights = 4; /* international */
43 e_ext.rxvol = e_ext.txvol = 256;
44 e_state = EPOINT_STATE_IDLE;
45 e_ext.number[0] = '\0';
46 e_extension_interface[0] = '\0';
47 memset(&e_callerinfo, 0, sizeof(struct caller_info));
48 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
49 memset(&e_connectinfo, 0, sizeof(struct connect_info));
50 memset(&e_redirinfo, 0, sizeof(struct redir_info));
51 memset(&e_capainfo, 0, sizeof(struct capa_info));
54 e_ruleset = ruleset_main;
56 e_rule = e_ruleset->rule_first;
61 e_match_to_action = NULL;
63 e_extdialing = e_dialinginfo.number;
67 // e_call_tone[0] = e_hold_tone[0] = '\0';
68 e_call_pattern /*= e_hold_pattern*/ = 0;
71 e_adminid = 0; // will be set, if call was initiated via admin socket
76 e_cbdialing[0] = '\0';
79 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
86 e_password_timeout = 0;
87 e_multipoint_cause = CAUSE_NOUSER;
88 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
89 e_dialing_queue[0] = '\0';
91 e_crypt_state = CM_ST_NULL;
92 e_crypt_keyengine_busy = 0;
93 e_crypt_info[0] = '\0';
96 e_tx_state = NOTIFY_STATE_ACTIVE;
97 e_rx_state = NOTIFY_STATE_ACTIVE;
98 e_call_cause = e_call_location = 0;
99 /*********************************
100 *********************************
101 ********* ATTENTION *************
102 *********************************
103 *********************************/
104 /* if you add new values, that must be initialized, also check if they must
105 * be initialized when doing callback
111 * EpointAppPBX destructor
113 EndpointAppPBX::~EndpointAppPBX(void)
115 class EndpointAppPBX *temp, **tempp;
119 tempp = &apppbx_first;
130 PERROR("error: endpoint not in endpoint's list, exitting.\n");
139 * trace header for application
141 void EndpointAppPBX::trace_header(char *name, int direction)
145 char msgtext[sizeof(_trace.name)];
149 /* init trace with given values */
150 start_trace(ea_endpoint->ep_serial,
152 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype),
153 e_dialinginfo.number,
156 ea_endpoint->ep_serial,
163 /* set new endpoint state
165 void EndpointAppPBX::new_state(int state)
168 if (e_state != state)
170 trace_header("NEW STATE", DIRECTION_NONE);
171 add_trace("state", "old", "%s", state_name[e_state]);
172 add_trace("state", "new", "%s", state_name[state]);
181 * out==0: incomming caller id, out==1: outgoing caller id
183 void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present)
185 struct interface *interface;
187 struct interface_msn *ifmsn;
188 struct interface_screen *ifscreen;
191 interface = interface_first;
194 if (!strcmp(e_callerinfo.interface, interface->name))
198 interface = interface->next;
202 /* screen incoming caller id */
205 /* check for MSN numbers, use first MSN if no match */
207 ifmsn = interface->ifmsn;
212 if (!strcmp(ifmsn->msn, id))
220 trace_header("SCREEN (found in list)", DIRECTION_IN);
221 add_trace("msn", NULL, "%s", id);
224 if (!ifmsn && msn1) // not in list, first msn given
226 trace_header("SCREEN (not found in list)", DIRECTION_IN);
227 add_trace("msn", "given", "%s", id);
228 add_trace("msn", "used", "%s", msn1);
230 UNCPY(id, msn1, idsize);
235 /* check screen list */
237 ifscreen = interface->ifscreen_out;
239 ifscreen = interface->ifscreen_in;
242 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
243 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
245 if (strchr(ifscreen->match,'%'))
247 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
251 if (!strcmp(ifscreen->match, id))
255 ifscreen = ifscreen->next;
257 if (ifscreen) // match
259 trace_header("SCREEN (found in list)", out?DIRECTION_OUT:DIRECTION_IN);
262 case INFO_NTYPE_UNKNOWN:
263 add_trace("given", "type", "unknown");
265 case INFO_NTYPE_SUBSCRIBER:
266 add_trace("given", "type", "subscriber");
268 case INFO_NTYPE_NATIONAL:
269 add_trace("given", "type", "national");
271 case INFO_NTYPE_INTERNATIONAL:
272 add_trace("given", "type", "international");
277 case INFO_PRESENT_ALLOWED:
278 add_trace("given", "present", "allowed");
280 case INFO_PRESENT_RESTRICTED:
281 add_trace("given", "present", "restricted");
283 case INFO_PRESENT_NOTAVAIL:
284 add_trace("given", "present", "not available");
287 add_trace("given", "id", "%s", id[0]?id:"<empty>");
288 if (ifscreen->result_type != -1)
290 *type = ifscreen->result_type;
293 case INFO_NTYPE_UNKNOWN:
294 add_trace("used", "type", "unknown");
296 case INFO_NTYPE_SUBSCRIBER:
297 add_trace("used", "type", "subscriber");
299 case INFO_NTYPE_NATIONAL:
300 add_trace("used", "type", "national");
302 case INFO_NTYPE_INTERNATIONAL:
303 add_trace("used", "type", "international");
307 if (ifscreen->result_present != -1)
309 *present = ifscreen->result_present;
312 case INFO_PRESENT_ALLOWED:
313 add_trace("used", "present", "allowed");
315 case INFO_PRESENT_RESTRICTED:
316 add_trace("used", "present", "restricted");
318 case INFO_PRESENT_NOTAVAIL:
319 add_trace("used", "present", "not available");
323 if (strchr(ifscreen->match,'%'))
325 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
326 UNCPY(id, ifscreen->result, idsize);
328 if (strchr(ifscreen->result,'%'))
330 *strchr(ifscreen->result,'%') = '\0';
331 UNCAT(id, suffix, idsize);
336 UNCPY(id, ifscreen->result, idsize);
339 add_trace("used", "id", "%s", id[0]?id:"<empty>");
345 /* release call and port (as specified)
347 void EndpointAppPBX::release(int release, int calllocation, int callcause, int portlocation, int portcause)
349 struct port_list *portlist;
350 struct message *message;
354 /* message to test call */
355 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", callcause, calllocation, 0);
357 /* if a release is pending */
358 if (release==RELEASE_CALL || release==RELEASE_ALL || release==RELEASE_PORT_CALLONLY)
360 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (callcause %d location %d)\n", ea_endpoint->ep_serial, callcause, calllocation);
361 if (ea_endpoint->ep_call_id)
363 call = find_call_id(ea_endpoint->ep_call_id);
365 call->release(ea_endpoint->ep_serial, 0, calllocation, callcause);
367 ea_endpoint->ep_call_id = 0;
370 if (release != RELEASE_PORT_CALLONLY)
373 call_release(e_hold_id, ea_endpoint->ep_serial, 1, calllocation, callcause);
378 if (release==RELEASE_ALL || release==RELEASE_PORT_CALLONLY)
380 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
381 while((portlist = ea_endpoint->ep_portlist))
383 if (portlist->port_id)
385 SPRINT(cause, "cause_%02x", portcause);
386 set_tone(portlist, cause);
387 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
388 message->param.disconnectinfo.cause = portcause;
389 message->param.disconnectinfo.location = portlocation;
390 message_put(message);
393 ea_endpoint->free_portlist(portlist);
396 /* if callback is enabled, call back with the given caller id */
399 /* reset some stuff */
400 new_state(EPOINT_STATE_IDLE);
401 memset(&e_connectinfo, 0, sizeof(struct connect_info));
402 memset(&e_redirinfo, 0, sizeof(struct redir_info));
403 e_start = e_stop = 0;
404 e_ruleset = ruleset_main;
406 e_rule = e_ruleset->rule_first;
408 e_action_timeout = 0;
410 e_match_to_action = NULL;
412 e_extdialing = e_dialinginfo.number;
419 e_multipoint_cause = CAUSE_NOUSER;
420 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
421 e_dialing_queue[0] = '\0';
423 e_crypt_state = CM_ST_NULL;
424 e_crypt_keyengine_busy = 0;
425 e_crypt_info[0] = '\0';
429 e_tx_state = NOTIFY_STATE_ACTIVE;
430 e_rx_state = NOTIFY_STATE_ACTIVE;
431 e_call_cause = e_call_location = 0;
433 /* the caller info of the callback user */
434 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
435 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
436 /* create dialing by callerinfo */
437 if (e_ext.number[0] && e_extension_interface[0])
439 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
440 /* create callback to the current terminal */
441 SCPY(e_dialinginfo.number, e_ext.number);
442 SCPY(e_dialinginfo.interfaces, e_extension_interface);
443 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
444 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
449 SCPY(e_dialinginfo.number, e_cbto);
452 /* numberrize caller id and use it to dial to the callback */
453 SCPY(e_dialinginfo.number, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
455 e_dialinginfo.itype = INFO_ITYPE_ISDN;
456 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
457 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.number);
462 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
463 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
469 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
470 void apply_callerid_restriction(int anon_ignore, int port_type, char *id, int *ntype, int *present, int *screen, char *voip, char *extension, char *name)
472 PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d voip='%s' extension='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (voip)?voip:"NULL", (extension)?extension:"NULL", (name)?name:"NULL");
474 /* caller id is not restricted, so we do nothing */
475 if (*present != INFO_PRESENT_RESTRICTED)
478 /* only extensions are restricted */
484 /* if we enabled anonymouse ignore */
488 /* else we remove the caller id */
492 *ntype = INFO_NTYPE_UNKNOWN;
494 // *screen = INFO_SCREEN_USER;
495 // maybe we should not make voip address anonymous
498 // maybe it's no fraud to present extension id
500 // extension[0] = '\0';
505 /* used display message to display callerid as available */
506 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *voip, char *extension, char *name)
508 static char display[81];
511 char *cid = numberrize_callerinfo(id, ntype);
513 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d voip='%s' extension='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (voip)?voip:"NULL", (extension)?extension:"NULL", (name)?name:"NULL");
524 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
526 /* internal extension's caller id */
527 if (extension[0] && e_ext.display_int)
530 SCAT(display, extension);
533 if (itype == INFO_ITYPE_VBOX)
534 SCAT(display, "(vbox)");
536 SCAT(display, "(int)");
539 /* external caller id */
540 if (!extension[0] && !voip[0] && e_ext.display_ext)
546 if (present == INFO_PRESENT_RESTRICTED)
547 SCAT(display, "anonymous");
549 SCAT(display, "unknown");
557 if (voip[0] && e_ext.display_voip)
559 if (!display[0] && cid[0])
566 /* display if callerid is anonymouse but available due anon-ignore */
567 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
570 SCAT(display, "unknown");
573 SCAT(display, " anon");
576 /* display if callerid is anonymouse but available due anon-ignore */
577 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
583 if (present == INFO_PRESENT_RESTRICTED)
584 SCAT(display, "anonymous");
586 SCAT(display, "unknown");
591 SCAT(display, " fake");
595 if (name[0] && e_ext.display_name)
597 if (!display[0] && cid[0])
608 * uses the current state to notify activity
610 void EndpointAppPBX::notify_active(void)
612 struct port_list *portlist = ea_endpoint->ep_portlist;
613 struct message *message;
618 case NOTIFY_STATE_ACTIVE:
619 /* we are already active, so we don't do anything */
622 case NOTIFY_STATE_SUSPEND:
623 notify = INFO_NOTIFY_USER_RESUMED;
626 set_tone(portlist, NULL);
627 portlist = portlist->next;
629 portlist = ea_endpoint->ep_portlist;
632 case NOTIFY_STATE_HOLD:
633 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
636 set_tone(portlist, NULL);
637 portlist = portlist->next;
639 portlist = ea_endpoint->ep_portlist;
642 case NOTIFY_STATE_CONFERENCE:
643 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
646 set_tone(portlist, NULL);
647 portlist = portlist->next;
649 portlist = ea_endpoint->ep_portlist;
653 PERROR("unknown e_tx_state = %d\n", e_tx_state);
659 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
660 message->param.notifyinfo.notify = notify;
661 message_put(message);
663 portlist = portlist->next;
669 * keypad functions during call. one example to use this is to put a call on hold or start a conference
671 void EndpointAppPBX::keypad_function(char digit)
674 /* we must be in a call, in order to send messages to the call */
675 if (e_ext.number[0] == '\0')
677 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
683 /* join conference */
685 if (ea_endpoint->ep_call_id == 0)
687 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
690 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
696 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
700 /* crypt key-exchange */
702 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
708 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
713 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
718 /* set tone pattern for port */
719 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
721 struct message *message;
726 /* store for suspended processes */
731 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no endpoint to notify tone.\n", ea_endpoint->ep_serial);
735 if (e_call_pattern /* pattern are provided */
736 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
737 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
738 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
739 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
740 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
741 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
742 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
743 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
744 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
745 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
746 && tone[0] && !!strncmp(tone,"crypt_*",6))
748 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
754 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
755 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
756 SCPY(message->param.tone.name, tone);
757 message_put(message);
764 * hunts an mISDNport that is available for an outgoing call
765 * if no ifname was given, any interface that is not an extension
768 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
770 struct interface *interface;
771 struct interface_port *ifport, *ifport_start;
772 struct mISDNport *mISDNport;
774 interface = interface_first;
776 /* first find the given interface or, if not given, one with no extension */
781 /* check for given interface */
784 if (!strcasecmp(interface->name, ifname))
786 /* found explicit interface */
787 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
788 add_trace("interface", NULL, "%s", ifname);
795 if (!interface->extension)
797 /* found non extension */
798 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
799 add_trace("interface", NULL, "%s", interface->name);
805 interface = interface->next;
808 /* see if interface has ports */
809 if (!interface->ifport)
812 trace_header("CHANNEL SELECTION (interface has no active ports, skipping)", DIRECTION_NONE);
813 add_trace("interface", NULL, "%s", interface->name);
815 interface = interface->next;
819 /* select port by algorithm */
820 ifport_start = interface->port;
822 if (interface->hunt == HUNT_ROUNDROBIN)
824 while(ifport_start->next && index<interface->hunt_next)
826 ifport_start = ifport_start->next;
829 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
830 add_trace("port", NULL, "%d", ifport_start->portnum);
831 add_trace("position", NULL, "%d", index);
836 ifport = ifport_start;
839 /* see if port is available */
840 if (!ifport->mISDNport)
842 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
843 add_trace("port", NULL, "%d", ifport->portnum);
844 add_trace("position", NULL, "%d", index);
848 mISDNport = ifport->mISDNport;
850 #warning admin block auch bei incomming calls
851 #warning calls releasen, wenn port entfernt wird, geblockt wird
852 /* see if port is administratively blocked */
855 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
856 add_trace("port", NULL, "%d", ifport->portnum);
857 add_trace("position", NULL, "%d", index);
862 /* see if link is up */
863 if (mISDNport->ptp && !mISDNport->l2link)
865 trace_header("CHANNEL SELECTION (port is ptp with layer 2 down, skipping)", DIRECTION_NONE);
866 add_trace("port", NULL, "%d", ifport->portnum);
867 add_trace("position", NULL, "%d", index);
872 /* check for channel form selection list */
874 selchannel = ifport->selchannel;
877 switch(selchannel->channel)
879 case CHANNEL_FREE: /* free channel */
880 if (mISDNport->b_inuse >= mISDNport->b_num)
881 break; /* all channel in use or reserverd */
884 while(i < mISDNport->b_num)
886 if (mISDNport->b_port[i] == NULL)
888 *channel = i+1+(i>=15);
889 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
890 add_trace("port", NULL, "%d", ifport->portnum);
891 add_trace("position", NULL, "%d", index);
892 add_trace("channel", NULL, "%d", *channel);
900 case CHANNEL_ANY: /* don't ask for channel */
901 if (mISDNport->b_inuse >= mISDNport->b_num)
903 break; /* all channel in use or reserverd */
905 trace_header("CHANNEL SELECTION (using 'any channel')", DIRECTION_NONE);
906 add_trace("port", NULL, "%d", ifport->portnum);
907 add_trace("position", NULL, "%d", index);
909 *channel = SEL_CHANNEL_ANY;
912 case CHANNEL_NO: /* call waiting */
913 trace_header("CHANNEL SELECTION (using 'no channel', call-waiting)", DIRECTION_NONE);
914 add_trace("port", NULL, "%d", ifport->portnum);
915 add_trace("position", NULL, "%d", index);
917 *channel = SEL_CHANNEL_NO;
921 if (selchannel->channel<1 || selchannel->channel==16)
922 break; /* invalid channels */
923 i = selchannel->channel-1-(selchannel->channel>=17);
924 if (i >= mISDNport->b_num)
925 break; /* channel not in port */
926 if (mISDNport->b_port[i] == NULL)
928 *channel = selchannel->channel;
929 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
930 add_trace("port", NULL, "%d", ifport->portnum);
931 add_trace("position", NULL, "%d", index);
932 add_trace("channel", NULL, "%d", *channel);
939 break; /* found channel */
940 selchannel = selchannel->next;
943 /* if channel was found, return mISDNport and channel */
946 /* setting next port to start next time */
947 if (interface->hunt == HUNT_ROUNDROBIN)
952 interface->hunt_next = index;
958 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
959 add_trace("port", NULL, "%d", ifport->portnum);
960 add_trace("position", NULL, "%d", index);
964 /* go next port, until all ports are checked */
966 ifport = ifport->next;
970 ifport = interface->ifport;
972 if (ifport != ifport_start)
975 return(NULL); /* no port found */
978 /* outgoing setup to port(s)
979 * ports will be created and a setup is sent if everything is ok. otherwhise
980 * the endpoint is destroyed.
982 void EndpointAppPBX::out_setup(void)
984 struct dialing_info dialinginfo;
986 // class pdss1 *pdss1;
987 struct port_list *portlist;
988 struct message *message;
990 int cause = CAUSE_RESSOURCEUNAVAIL;
993 struct mISDNport *mISDNport;
996 class EndpointAppPBX *atemp;
997 // char allowed_ports[256];
1001 char ifname[sizeof(e_ext.interfaces)],
1003 struct port_settings port_settings;
1006 /* create settings for creating port */
1007 memset(&port_settings, 0, sizeof(port_settings));
1008 if (e_ext.tones_dir)
1009 SCPY(port_settings.tones_dir, e_ext.tones_dir);
1011 SCPY(port_settings.tones_dir, options.tones_dir);
1012 port_settings.tout_setup = e_ext.tout_setup;
1013 port_settings.tout_dialing = e_ext.tout_dialing;
1014 port_settings.tout_proceeding = e_ext.tout_proceeding;
1015 port_settings.tout_alerting = e_ext.tout_alerting;
1016 port_settings.tout_disconnect = e_ext.tout_disconnect;
1017 // port_settings.tout_hold = e_ext.tout_hold;
1018 // port_settings.tout_park = e_ext.tout_park;
1019 port_settings.no_seconds = e_ext.no_seconds;
1021 /* NOTE: currently the try_card feature is not supported. it should be used later to try another card, if the outgoing call fails on one port */
1023 /* check what dialinginfo.itype we got */
1024 switch(e_dialinginfo.itype)
1026 /* *********************** call to extension or vbox */
1027 case INFO_ITYPE_ISDN_EXTENSION:
1028 /* check if we deny incoming calls when we use an extension */
1029 if (e_ext.noknocking)
1031 atemp = apppbx_first;
1035 if (!strcmp(atemp->e_ext.number, e_ext.number))
1037 atemp = atemp->next;
1041 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
1042 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ call, port */
1043 return; /* must exit here */
1046 /* FALL THROUGH !!!! */
1047 case INFO_ITYPE_VBOX:
1048 /* get dialed extension's info */
1049 // SCPY(exten, e_dialinginfo.number);
1050 // if (strchr(exten, ','))
1051 // *strchr(exten, ',') = '\0';
1052 // if (!read_extension(&e_ext, exten))
1053 if (!read_extension(&e_ext, e_dialinginfo.number))
1055 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.number);
1056 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1057 return; /* must exit here */
1060 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
1062 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
1067 /* string from unconditional call forward (cfu) */
1071 /* present to forwarded party */
1072 if (e_ext.anon_ignore && e_callerinfo.id[0])
1074 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1076 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1080 /* string from busy call forward (cfb) */
1084 class EndpointAppPBX *checkapp = apppbx_first;
1087 if (checkapp != this) /* any other endpoint except our own */
1089 if (!strcmp(checkapp->e_ext.number, e_ext.number))
1091 /* present to forwarded party */
1092 if (e_ext.anon_ignore && e_callerinfo.id[0])
1094 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1096 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1100 checkapp = checkapp->next;
1104 /* string from no-response call forward (cfnr) */
1108 /* when cfnr is done, out_setup() will setup the call */
1111 /* present to forwarded party */
1112 if (e_ext.anon_ignore && e_callerinfo.id[0])
1114 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1118 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1120 e_cfnr_release = now + e_ext.cfnr_delay;
1121 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
1122 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) setting time for call-forward-busy to %s with delay %ld.\n", ea_endpoint->ep_serial, e_ext.cfnr, e_ext.cfnr_delay);
1126 /* call to all internal interfaces */
1127 p = e_ext.interfaces;
1128 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple calls for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.number, p);
1132 while(*p!=',' && *p!='\0')
1134 SCCAT(ifname, *p++);
1137 /* found interface */
1138 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
1139 /* hunt for mISDNport and create Port */
1140 mISDNport = hunt_port(ifname, &channel);
1143 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
1144 add_trace("interface", NULL, "%s", ifname);
1148 /* creating INTERNAL port */
1149 SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
1150 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport.channel_force);
1153 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port '%s' failed to create\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1154 goto check_anycall_intern;
1156 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1157 memset(&dialinginfo, 0, sizeof(dialinginfo));
1158 SCPY(dialinginfo.number, e_dialinginfo.number);
1159 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1160 dialinginfo.ntype = e_dialinginfo.ntype;
1161 /* create port_list relation */
1162 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->is_earlyb);
1165 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1167 goto check_anycall_intern;
1169 /* directory.list */
1170 if (e_callerinfo.id[0] && (e_ext.centrex || e_ext.display_name))
1172 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1174 SCPY(e_callerinfo.name, dirname);
1176 // dss1 = (class Pdss1 *)port;
1178 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
1179 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1180 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1181 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1182 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1183 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1184 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1185 //terminal if (e_dialinginfo.number)
1186 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
1187 /* handle restricted caller ids */
1188 apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name);
1189 apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, NULL, message->param.setup.redirinfo.voip, message->param.setup.redirinfo.intern, 0);
1190 /* display callerid if desired for extension */
1191 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name));
1192 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1193 /* use cnip, if enabld */
1195 message->param.setup.callerinfo.name[0] = '\0';
1196 /* screen clip if prefix is required */
1197 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1199 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1200 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
1201 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1203 /* use internal caller id */
1204 if (e_callerinfo.intern[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1206 SCPY(message->param.setup.callerinfo.id, e_callerinfo.intern);
1207 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1209 message_put(message);
1210 logmessage(message);
1214 /* string from parallel call forward (cfp) */
1218 if (e_ext.anon_ignore && e_callerinfo.id[0])
1220 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1224 vbox_only: /* entry point for answering machine only */
1225 cfu_only: /* entry point for cfu */
1226 cfb_only: /* entry point for cfb */
1227 cfnr_only: /* entry point for cfnr */
1228 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number, p);
1232 /* only if vbox should be dialed, and terminal is given */
1234 if (!strcmp(p, "vbox") && e_ext.number[0])
1236 /* go to the end of p */
1239 /* answering vbox call */
1240 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1242 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1244 PERROR("EPOINT(%d) no mem for port\n", ea_endpoint->ep_serial);
1247 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1248 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1252 while(*p!=',' && *p!='\0')
1258 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1259 /* hunt for mISDNport and create Port */
1260 mISDNport = mISDNport_first;
1264 /* check for external or given interface */
1265 if (((!e_dialinginfo.interfaces[0])&&mISDNport->iftype==IF_EXTERN) || !strcmp(mISDNport->interface_name, e_dialinginfo.interfaces))
1267 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) interface '%s' found\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1268 cause = CAUSE_NOCHANNEL; /* when failing: out of channels */
1269 /* if PTP, skip all down links */
1270 if (mISDNport->ptp && !mISDNport->l2link)
1272 trace_header("INTERFACE (layer 2 is down)", DIRECTION_NONE);
1273 add_trace("interface", NULL, "%s", mISDNport->interface_name);
1275 mISDNport = mISDNport->next;
1278 /* if no channel is available */
1279 if (mISDNport->multilink || !mISDNport->ntmode || mISDNport->ptp)
1283 ii = mISDNport->b_num;
1286 if (mISDNport->b_state[i])
1290 if (use >= mISDNport->b_num)
1292 trace_header("INTERFACE (no free channel)", DIRECTION_NONE);
1293 add_trace("interface", NULL, "%s", mISDNport->interface_name);
1295 mISDNport = mISDNport->next;
1299 /* found interface */
1300 trace_header("INTERFACE (found)", DIRECTION_NONE);
1301 add_trace("interface", NULL, "%s", mISDNport->interface_name);
1305 mISDNport = mISDNport->next;
1309 /* creating EXTERNAL port*/
1310 SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
1311 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings);
1312 earlyb = mISDNport->is_earlyb;
1316 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1317 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1323 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1324 goto check_anycall_intern;
1326 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1327 memset(&dialinginfo, 0, sizeof(dialinginfo));
1328 SCPY(dialinginfo.number, cfp);
1329 dialinginfo.itype = INFO_ITYPE_EXTERN;
1330 dialinginfo.ntype = e_dialinginfo.ntype;
1331 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1334 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1336 goto check_anycall_intern;
1338 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
1339 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1340 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1341 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1342 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1343 /* if clip is hidden */
1344 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1346 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1347 SCPY(message->param.setup.callerinfo.intern, e_ext.number);
1348 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1349 message->param.setup.callerinfo.present = e_ext.callerid_present;
1351 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1352 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1353 //terminal if (e_dialinginfo.number)
1354 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
1355 /* handle restricted caller ids */
1356 apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name);
1357 apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, NULL, message->param.setup.redirinfo.voip, message->param.setup.redirinfo.intern, 0);
1358 /* display callerid if desired for extension */
1359 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name));
1360 message_put(message);
1361 logmessage(message);
1365 check_anycall_intern:
1366 /* now we have all ports created */
1369 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1371 if (!ea_endpoint->ep_call_id)
1373 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1374 return; /* must exit here */
1378 /* *********************** external call */
1380 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number);
1381 /* call to extenal interfaces */
1382 p = e_dialinginfo.number;
1386 while(*p!=',' && *p!='\0')
1387 SCCAT(number, *p++);
1391 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to number '%s' interface '%s'\n", ea_endpoint->ep_serial, number, e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1392 /* hunt for mISDNport and create Port */
1393 mISDNport = mISDNport_first;
1397 /* check for external or given interface */
1398 if ((!e_dialinginfo.interfaces[0]&&mISDNport->iftype==IF_EXTERN) || !strcmp(mISDNport->interface_name, e_dialinginfo.interfaces))
1400 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) interface '%s' found\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1401 cause = CAUSE_NOCHANNEL; /* when failing: out of channels */
1402 /* if PTP, skip all down links */
1403 if (mISDNport->ptp && !mISDNport->l2link)
1405 trace_header("INTERFACE (layer 2 is down)", DIRECTION_NONE);
1406 add_trace("interface", NULL, "%s", mISDNport->interface_name);
1408 mISDNport = mISDNport->next;
1411 /* if no channel is available */
1412 if (mISDNport->multilink || !mISDNport->ntmode || mISDNport->ptp)
1416 ii = mISDNport->b_num;
1419 if (mISDNport->b_state[i])
1423 if (use >= mISDNport->b_num)
1425 trace_header("INTERFACE (no free channel)", DIRECTION_NONE);
1426 add_trace("interface", NULL, "%s", mISDNport->interface_name);
1428 mISDNport = mISDNport->next;
1432 /* found interface */
1433 trace_header("INTERFACE (found)", DIRECTION_NONE);
1434 add_trace("interface", NULL, "%s", mISDNport->interface_name);
1438 mISDNport = mISDNport->next;
1442 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1443 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1445 goto check_anycall_extern;
1447 /* creating EXTERNAL port*/
1448 SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
1449 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings);
1452 PERROR("EPOINT(%d) no memory for external port, exitting\n", ea_endpoint->ep_serial);
1455 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1456 memset(&dialinginfo, 0, sizeof(dialinginfo));
1457 SCPY(dialinginfo.number, number);
1458 dialinginfo.itype = INFO_ITYPE_EXTERN;
1459 dialinginfo.ntype = e_dialinginfo.ntype;
1460 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->is_earlyb);
1463 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1465 goto check_anycall_extern;
1467 // dss1 = (class Pdss1 *)port;
1468 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
1469 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1470 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1471 SCPY(message->param.setup.dialinginfo.number, number);
1472 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1473 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1474 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1475 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1476 //terminal if (e_dialinginfo.number)
1477 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
1478 /* handle restricted caller ids */
1479 apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name);
1480 apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, NULL, message->param.setup.redirinfo.voip, message->param.setup.redirinfo.intern, 0);
1481 /* display callerid if desired for extension */
1482 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name));
1483 message_put(message);
1484 logmessage(message);
1488 check_anycall_extern:
1489 /* now we have all ports created */
1492 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1494 if (!ea_endpoint->ep_call_id)
1496 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1497 return; /* must exit here */
1505 /* handler for endpoint
1509 int EndpointAppPBX::handler(void)
1511 if (e_crypt_state!=CM_ST_NULL)
1516 /* process answering machine (play) handling */
1519 if (e_action->index == ACTION_VBOX_PLAY)
1522 /* process action timeout */
1523 if (e_action_timeout)
1524 if (now_d >= e_action_timeout)
1526 if (e_state!=EPOINT_STATE_CONNECT)
1529 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1530 e_multipoint_cause = CAUSE_NOUSER;
1531 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
1532 new_state(EPOINT_STATE_IN_OVERLAP);
1535 return(1); /* we must exit, because our endpoint might be gone */
1537 e_action_timeout = 0;
1540 /* process action timeout */
1541 if (e_match_timeout)
1542 if (now_d >= e_match_timeout)
1545 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1547 return(1); /* we must exit, because our endpoint might be gone */
1552 /* process redialing (epoint redials to port) */
1555 if (now_d >= e_redial)
1558 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1560 new_state(EPOINT_STATE_OUT_SETUP);
1561 /* call special setup routine */
1568 /* process powerdialing (epoint redials to epoint) */
1569 if (e_powerdialing > 0)
1571 if (now_d >= e_powerdialing)
1573 e_powerdialing = -1; /* leave power dialing on */
1574 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1577 e_ruleset = ruleset_main;
1579 e_rule = e_ruleset->rule_first;
1581 new_state(EPOINT_STATE_IN_OVERLAP);
1587 /* process call forward no response */
1590 struct port_list *portlist;
1591 struct message *message;
1593 if (now >= e_cfnr_release)
1595 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1598 /* release all ports */
1599 while((portlist = ea_endpoint->ep_portlist))
1601 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1602 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1603 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1604 message_put(message);
1605 logmessage(message);
1606 ea_endpoint->free_portlist(portlist);
1609 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
1610 message->param.channel = CHANNEL_STATE_HOLD;
1611 message_put(message);
1612 /* indicate no patterns */
1613 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
1614 message_put(message);
1615 /* set setup state, since we have no response from the new call */
1616 new_state(EPOINT_STATE_OUT_SETUP);
1621 if (now >= e_cfnr_call)
1623 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1629 /* handle connection to user */
1630 if (e_state == EPOINT_STATE_IDLE)
1632 /* epoint is idle, check callback */
1634 if (now_d >= e_callback)
1636 e_callback = 0; /* done with callback */
1637 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1638 new_state(EPOINT_STATE_OUT_SETUP);
1644 /* check for password timeout */
1646 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1648 struct port_list *portlist;
1650 if (now >= e_password_timeout)
1652 e_ruleset = ruleset_main;
1654 e_rule = e_ruleset->rule_first;
1656 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1657 trace_header("PASSWORD timeout", DIRECTION_NONE);
1659 e_connectedmode = 0;
1661 new_state(EPOINT_STATE_OUT_DISCONNECT);
1662 portlist = ea_endpoint->ep_portlist;
1665 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1666 set_tone(portlist, "cause_10");
1676 /* doing a hookflash */
1677 void EndpointAppPBX::hookflash(void)
1681 /* be sure that we are active */
1683 e_tx_state = NOTIFY_STATE_ACTIVE;
1685 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1687 if (ea_endpoint->ep_use > 1)
1689 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1692 /* dialtone after pressing the hash key */
1693 process_hangup(e_call_cause, e_call_location);
1694 e_multipoint_cause = CAUSE_NOUSER;
1695 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
1696 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1699 port->set_echotest(0);
1701 if (ea_endpoint->ep_call_id)
1703 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1705 e_ruleset = ruleset_main;
1707 e_rule = e_ruleset->rule_first;
1709 new_state(EPOINT_STATE_IN_OVERLAP);
1710 e_connectedmode = 1;
1711 SCPY(e_dialinginfo.number, e_ext.prefix);
1712 e_extdialing = e_dialinginfo.number;
1714 if (e_dialinginfo.number[0])
1716 set_tone(ea_endpoint->ep_portlist, "dialing");
1720 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1727 /* messages from port
1729 /* port MESSAGE_SETUP */
1730 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1732 struct message *message;
1735 char extension1[32];
1737 int writeext; /* flags need to write extension after modification */
1740 portlist->port_type = param->setup.port_type;
1741 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1742 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1743 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1744 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1745 e_dtmf = param->setup.dtmf;
1747 /* screen incoming caller id */
1748 screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present);
1749 colp, outclip, outcolp
1751 /* process extension */
1752 if (e_callerinfo.itype == INFO_ITYPE_INTERN)
1754 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1755 /* port makes call from extension */
1756 SCPY(e_callerinfo.intern, e_callerinfo.id);
1757 SCPY(e_ext.number, e_callerinfo.intern);
1758 SCPY(e_extension_interface, e_callerinfo.interface);
1761 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1763 trace_header("SETUP", DIRECTION_IN);
1764 if (e_callerinfo.intern[0])
1765 add_trace("extension", NULL, "%s", e_callerinfo.intern);
1766 add_trace("caller id", "number", "%s", numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype));
1767 if (e_callerinfo.present == INFO_PRESENT_RESTRICTED)
1768 add_trace("caller id", "present", "restricted");
1769 if (e_redirinfo.id[0])
1771 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(e_redirinfo.id, e_redirinfo.ntype));
1772 if (e_redirinfo.present == INFO_PRESENT_RESTRICTED)
1773 add_trace("redir'ing", "present", "restricted");
1775 if (e_dialinginfo.number)
1776 add_trace("dialing", "number", "%s", e_dialinginfo.number));
1779 if (e_callerinfo.itype == INFO_ITYPE_INTERN)
1781 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1783 /* get extension's info about caller */
1784 if (!read_extension(&e_ext, e_ext.number))
1786 /* extension doesn't exist */
1787 trace_header("EXTENSION (not created)", DIRECTION_IN);
1788 add_trace("extension", NULL, "%s", e_ext.number);
1790 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1791 new_state(EPOINT_STATE_OUT_DISCONNECT);
1792 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1793 e_ext.number[0] = '\0'; /* no terminal */
1798 /* put prefix (next) in front of e_dialinginfo.number */
1801 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.number);
1802 SCPY(e_dialinginfo.number, buffer);
1803 e_ext.next[0] = '\0';
1805 } else if (e_ext.prefix[0])
1807 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.number);
1808 SCPY(e_dialinginfo.number, buffer);
1811 /* screen caller id */
1812 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1814 SCPY(e_callerinfo.name, e_ext.name);
1815 /* use caller id (or if exist: id_next_call) for this call */
1816 if (e_ext.id_next_call_present >= 0)
1818 SCPY(e_callerinfo.id, e_ext.id_next_call);
1819 /* if we restrict the pesentation */
1820 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1821 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1822 else e_callerinfo.present = e_ext.id_next_call_present;
1823 e_callerinfo.ntype = e_ext.id_next_call_type;
1824 e_ext.id_next_call_present = -1;
1828 SCPY(e_callerinfo.id, e_ext.callerid);
1829 /* if we restrict the pesentation */
1830 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1831 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1832 else e_callerinfo.present = e_ext.callerid_present;
1833 e_callerinfo.ntype = e_ext.callerid_type;
1836 /* extension is written */
1838 write_extension(&e_ext, e_ext.number);
1840 /* set volume of rx and tx */
1841 if (param->setup.callerinfo.itype == INFO_ITYPE_INTERN)
1842 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
1844 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1845 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1846 message->param.mISDNsignal.rxvol = e_ext.txvol;
1847 message->param.mISDNsignal.txvol = e_ext.rxvol;
1848 message_put(message);
1851 /* start recording if enabled */
1852 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1854 /* check if we are a terminal */
1855 if (e_ext.number[0] == '\0')
1856 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1859 port = find_port_id(portlist->port_id);
1861 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1866 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1867 /* no terminal identification */
1868 e_ext.number[0] = '\0';
1869 e_extension_interface[0] = '\0';
1870 memset(&e_ext, 0, sizeof(e_ext));
1871 e_ext.rights = 4; /* right to dial internat */
1875 e_ruleset = ruleset_main;
1877 e_rule = e_ruleset->rule_first;
1879 e_extdialing = e_dialinginfo.number;
1880 new_state(EPOINT_STATE_IN_SETUP);
1881 if (e_dialinginfo.number[0])
1883 set_tone(portlist, "dialing");
1886 if (e_ext.number[0])
1887 set_tone(portlist, "dialpbx");
1889 set_tone(portlist, "dialtone");
1892 if (e_state == EPOINT_STATE_IN_SETUP)
1894 /* request MORE info, if not already at higher state */
1895 new_state(EPOINT_STATE_IN_OVERLAP);
1896 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1897 message_put(message);
1898 logmessage(message);
1902 /* port MESSAGE_INFORMATION */
1903 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1905 trace_header("INFORMATION", DIRECTION_IN);
1906 add_trace("dialing", NULL, "%s", param->information.number);
1907 if (param->information.sending_complete)
1908 add_trace("complete", NULL, NULL);
1912 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1915 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received dialing information, so dtmf is now disabled, to prevent double detection by keypad+dtmf.\n", ea_endpoint->ep_serial, param->information.number, e_ext.number, e_callerinfo.id);
1919 /* if vbox_play is done, the information are just used as they come */
1921 if (e_action->index == ACTION_VBOX_PLAY)
1923 /* concat dialing string */
1924 SCAT(e_dialinginfo.number, param->information.number);
1929 /* keypad when disconnect but in connected mode */
1930 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1932 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.number);
1933 /* processing keypad function */
1934 if (param->information.number[0] == '0')
1941 /* keypad when connected */
1942 if (e_state == EPOINT_STATE_CONNECT && e_ext.keypad)
1944 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.number);
1945 /* processing keypad function */
1946 if (param->information.number[0] == '0')
1950 if (param->information.number[0])
1951 keypad_function(param->information.number[0]);
1954 if (e_state != EPOINT_STATE_IN_OVERLAP)
1956 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in overlap, or connect state.\n", ea_endpoint->ep_serial);
1959 if (!param->information.number[0])
1961 if (e_dialinginfo.number[0]=='\0' && !e_action)
1963 set_tone(portlist, "dialing");
1966 if (e_action->index==ACTION_OUTDIAL
1967 || e_action->index==ACTION_EXTERNAL)
1970 set_tone(portlist, "dialing");
1971 else if (!e_extdialing[0])
1972 set_tone(portlist, "dialing");
1974 /* concat dialing string */
1975 SCAT(e_dialinginfo.number, param->information.number);
1979 /* port MESSAGE_DTMF */
1980 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1982 trace_header("DTMF", DIRECTION_IN);
1983 add_trace("digit", NULL, "%c", param->dtmf);
1985 /* only if dtmf detection is enabled */
1988 PDEBUG(DEBUG_EPOINT, "dtmf detection is disabled\n");
1993 NOTE: vbox is now handled due to overlap state
1994 /* if vbox_play is done, the dtmf digits are just used as they come */
1996 if (e_action->index == ACTION_VBOX_PLAY)
1998 /* concat dialing string */
1999 if (strlen(e_dialinginfo.number)+1 < sizeof(e_dialinginfo.number))
2001 e_dialinginfo.number[strlen(e_dialinginfo.number)+1] = '\0';
2002 e_dialinginfo.number[strlen(e_dialinginfo.number)] = param->dtmf;
2005 /* continue to process *X# sequences */
2009 /* check for *X# sequence */
2010 if (e_state == EPOINT_STATE_CONNECT)
2012 if (e_dtmf_time+3 < now)
2014 /* the last digit was too far in the past to be a sequence */
2015 if (param->dtmf == '*')
2016 /* only start is allowed in the sequence */
2022 /* we have a sequence of digits, see what we got */
2023 if (param->dtmf == '*')
2025 else if (param->dtmf>='0' && param->dtmf<='9')
2027 /* we need to have a star before we receive the digit of the sequence */
2028 if (e_dtmf_last == '*')
2029 e_dtmf_last = param->dtmf;
2030 } else if (param->dtmf == '#')
2033 if (e_dtmf_last>='0' && e_dtmf_last<='9')
2035 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
2036 if (e_dtmf_last == '0')
2041 /* processing keypad function */
2043 keypad_function(e_dtmf_last);
2049 /* set last time of dtmf */
2054 /* check for ## hookflash during dialing */
2056 if (e_action->index==ACTION_PASSWORD
2057 || e_action->index==ACTION_PASSWORD_WRITE)
2059 if (param->dtmf=='#') /* current digit is '#' */
2061 if (e_state==EPOINT_STATE_IN_DISCONNECT
2062 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
2079 /* dialing using dtmf digit */
2080 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
2082 if (e_dialinginfo.number[0]=='\0' && !e_action)
2084 set_tone(portlist, "dialing");
2086 /* concat dialing string */
2087 if (strlen(e_dialinginfo.number)+1 < sizeof(e_dialinginfo.number))
2089 e_dialinginfo.number[strlen(e_dialinginfo.number)+1] = '\0';
2090 e_dialinginfo.number[strlen(e_dialinginfo.number)] = param->dtmf;
2096 /* port MESSAGE_CRYPT */
2097 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
2099 /* send crypt response to cryptman */
2100 if (param->crypt.type == CR_MESSAGE_IND)
2101 cryptman_msg2man(param->crypt.data, param->crypt.len);
2103 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2106 /* port MESSAGE_OVERLAP */
2107 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
2109 struct message *message;
2111 /* signal to call tool */
2112 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
2114 trace_header("SETUP ACKNOWLEDGE", DIRECTION_IN);
2116 if (e_dialing_queue[0] && portlist)
2118 /* send what we have not dialed yet, because we had no setup complete */
2119 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
2120 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2121 SCPY(message->param.information.number, e_dialing_queue);
2122 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
2123 message_put(message);
2124 logmessage(message);
2125 e_dialing_queue[0] = '\0';
2127 /* check if pattern is available */
2128 if (!ea_endpoint->ep_portlist->next && portlist->earlyb) /* one port_list relation and tones available */
2130 /* indicate patterns */
2131 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2132 message_put(message);
2134 /* connect audio, if not already */
2135 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2136 message->param.channel = CHANNEL_STATE_CONNECT;
2137 message_put(message);
2140 /* indicate no patterns */
2141 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
2142 message_put(message);
2144 /* disconnect audio, if not already */
2145 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2146 message->param.channel = CHANNEL_STATE_HOLD;
2147 message_put(message);
2149 new_state(EPOINT_STATE_OUT_OVERLAP);
2150 /* if we are in a call */
2151 if (ea_endpoint->ep_call_id)
2153 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2154 memcpy(&message->param, param, sizeof(union parameter));
2155 message_put(message);
2159 /* port MESSAGE_PROCEEDING */
2160 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2162 struct message *message;
2164 /* signal to call tool */
2165 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
2167 trace_header("PROCEEDING", DIRECTION_IN);
2169 e_state = EPOINT_STATE_OUT_PROCEEDING;
2170 /* check if pattern is availatle */
2171 if (!ea_endpoint->ep_portlist->next && (portlist->earlyb || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2173 /* indicate patterns */
2174 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2175 message_put(message);
2177 /* connect audio, if not already */
2178 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2179 message->param.channel = CHANNEL_STATE_CONNECT;
2180 message_put(message);
2183 /* indicate no patterns */
2184 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
2185 message_put(message);
2187 /* disconnect audio, if not already */
2188 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2189 message->param.channel = CHANNEL_STATE_HOLD;
2190 message_put(message);
2192 /* if we are in a call */
2193 if (ea_endpoint->ep_call_id)
2195 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2196 memcpy(&message->param, param, sizeof(union parameter));
2197 message_put(message);
2201 /* port MESSAGE_ALERTING */
2202 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
2204 struct message *message;
2206 /* signal to call tool */
2207 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
2209 trace_header("ALERTING", DIRECTION_IN);
2211 new_state(EPOINT_STATE_OUT_ALERTING);
2212 /* check if pattern is available */
2213 if (!ea_endpoint->ep_portlist->next && (portlist->earlyb || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2215 /* indicate patterns */
2216 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2217 message_put(message);
2219 /* connect audio, if not already */
2220 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2221 message->param.channel = CHANNEL_STATE_CONNECT;
2222 message_put(message);
2225 /* indicate no patterns */
2226 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
2227 message_put(message);
2229 /* disconnect audio, if not already */
2230 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2231 message->param.channel = CHANNEL_STATE_HOLD;
2232 message_put(message);
2234 /* if we are in a call */
2235 if (ea_endpoint->ep_call_id)
2237 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2238 memcpy(&message->param, param, sizeof(union parameter));
2239 message_put(message);
2243 /* port MESSAGE_CONNECT */
2244 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2246 struct message *message;
2248 unsigned long port_id = portlist->port_id;
2249 struct port_list *tportlist;
2252 /* signal to call tool */
2253 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2255 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2256 trace_header("CONNECT", DIRECTION_IN);
2257 if (e_connectinfo.intern[0])
2258 add_trace("extension", NULL, "%s", e_connectinfo.intern);
2259 add_trace("connect id", "number", "%s", numberrize_callerinfo(e_connectinfo.id, e_connectinfo.ntype));
2260 if (e_connectinfo.present == INFO_PRESENT_RESTRICTED)
2261 add_trace("connect id", "present", "restricted");
2263 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2264 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2266 tportlist = ea_endpoint->ep_portlist;
2267 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2268 tportlist = tportlist->next;
2269 if (tportlist->port_id == port_id)
2271 PERROR("EPOINT(%d) software error: this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2274 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2275 message->param.disconnectinfo.cause = 26; /* non selected user clearing */
2276 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2277 message_put(message);
2278 logmessage(message);
2279 ea_endpoint->free_portlist(tportlist);
2281 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2285 /* screen incoming caller id */
2286 screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present);
2288 /* screen connected name */
2290 SCPY(e_connectinfo.name, e_ext.name);
2292 /* add internal id to colp */
2293 SCPY(e_connectinfo.intern, e_ext.number);
2295 /* we store the connected port number */
2296 SCPY(e_extension_interface, e_connectinfo.interfaces);
2298 /* for internal and am calls, we get the extension's id */
2299 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2301 SCPY(e_connectinfo.id, e_ext.callerid);
2302 SCPY(e_connectinfo.intern, e_ext.number);
2303 e_connectinfo.itype = INFO_ITYPE_INTERN;
2304 e_connectinfo.ntype = e_ext.callerid_type;
2305 e_connectinfo.present = e_ext.callerid_present;
2307 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2309 e_connectinfo.itype = INFO_ITYPE_VBOX;
2310 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2313 new_state(EPOINT_STATE_CONNECT);
2315 /* set volume of rx and tx */
2316 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2318 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2319 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2320 message->param.mISDNsignal.rxvol = e_ext.txvol;
2321 message->param.mISDNsignal.txvol = e_ext.rxvol;
2322 message_put(message);
2325 e_cfnr_call = e_cfnr_release = 0;
2326 if (e_ext.number[0])
2327 e_dtmf = 1; /* allow dtmf */
2328 // if (call_countrelations(ea_endpoint->ep_call_id) == 2)
2331 /* other calls with no caller id (or not available for the extension) and force colp */
2332 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2334 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2335 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2337 port = find_port_id(portlist->port_id);
2340 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.number, &e_connectinfo.ntype));
2341 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2345 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2346 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2347 message_put(message);
2349 if (ea_endpoint->ep_call_id)
2351 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2352 message->param.channel = CHANNEL_STATE_CONNECT;
2353 message_put(message);
2354 } else if (!e_adminid)
2357 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2358 SCPY(e_ext.number, e_cbcaller);
2359 new_state(EPOINT_STATE_IN_OVERLAP);
2360 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2362 /* get extension's info about terminal */
2363 if (!read_extension(&e_ext, e_ext.number))
2365 /* extension doesn't exist */
2366 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2367 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2368 new_state(EPOINT_STATE_OUT_DISCONNECT);
2369 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2373 /* put prefix in front of e_cbdialing */
2374 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2375 SCPY(e_dialinginfo.number, buffer);
2376 e_dialinginfo.itype = INFO_ITYPE_EXTERN;
2377 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2379 /* use caller id (or if exist: id_next_call) for this call */
2380 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2381 SCPY(e_callerinfo.intern, e_ext.number);
2382 if (e_ext.id_next_call_present >= 0)
2384 SCPY(e_callerinfo.id, e_ext.id_next_call);
2385 e_callerinfo.present = e_ext.id_next_call_present;
2386 e_callerinfo.ntype = e_ext.id_next_call_type;
2387 e_ext.id_next_call_present = -1;
2388 /* extension is written */
2389 write_extension(&e_ext, e_ext.number);
2392 SCPY(e_callerinfo.id, e_ext.callerid);
2393 e_callerinfo.present = e_ext.callerid_present;
2394 e_callerinfo.ntype = e_ext.callerid_type;
2397 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2400 /* check if caller id is NOT authenticated */
2401 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2403 /* make call state to enter password */
2404 new_state(EPOINT_STATE_IN_OVERLAP);
2405 e_action = &action_password_write;
2406 e_match_timeout = 0;
2407 e_match_to_action = NULL;
2408 e_dialinginfo.number[0] = '\0';
2409 e_extdialing = strchr(e_dialinginfo.number, '\0');
2410 e_password_timeout = now+20;
2414 /* incoming call (callback) */
2415 e_ruleset = ruleset_main;
2417 e_rule = e_ruleset->rule_first;
2419 e_extdialing = e_dialinginfo.number;
2420 if (e_dialinginfo.number[0])
2422 set_tone(portlist, "dialing");
2426 set_tone(portlist, "dialpbx");
2429 } else /* testcall */
2431 set_tone(portlist, "hold");
2434 /* start recording if enabled, not when answering machine answers */
2435 if (param->connectinfo.itype!=INFO_ITYPE_VBOX && e_ext.number[0] && e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
2437 /* check if we are a terminal */
2438 if (e_ext.number[0] == '\0')
2439 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2442 port = find_port_id(portlist->port_id);
2444 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2449 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2450 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2452 struct message *message;
2454 unsigned long port_id = portlist->port_id;
2458 /* signal to call tool */
2459 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2461 trace_header((message_type==MESSAGE_DISCONNECT)?"DISCONNECT":"RELEASE", DIRECTION_IN);
2462 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
2463 add_trace("cause", "location", "%d", param->disconnectinfo.location);
2466 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2467 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2469 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2474 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current multipoint cause %d location %d, received cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2475 if (param->disconnectinfo.cause == CAUSE_REJECTED) /* call rejected */
2477 e_multipoint_cause = CAUSE_REJECTED;
2478 e_multipoint_location = param->disconnectinfo.location;
2480 if (param->disconnectinfo.cause==CAUSE_NORMAL && e_multipoint_cause!=CAUSE_REJECTED) /* reject via hangup */
2482 e_multipoint_cause = CAUSE_NORMAL;
2483 e_multipoint_location = param->disconnectinfo.location;
2485 if (param->disconnectinfo.cause==CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* busy */
2487 e_multipoint_cause = CAUSE_BUSY;
2488 e_multipoint_location = param->disconnectinfo.location;
2490 if (param->disconnectinfo.cause==CAUSE_OUTOFORDER && e_multipoint_cause!=CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* no L1 */
2492 e_multipoint_cause = CAUSE_OUTOFORDER;
2493 e_multipoint_location = param->disconnectinfo.location;
2495 if (param->disconnectinfo.cause!=CAUSE_NOUSER && e_multipoint_cause!=CAUSE_OUTOFORDER && e_multipoint_cause!=CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* anything but not 18 */
2497 e_multipoint_cause = param->disconnectinfo.cause;
2498 e_multipoint_location = param->disconnectinfo.location;
2500 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2502 /* check if we have more than one portlist relation and we just ignore the disconnect */
2503 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2505 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2506 portlist = ea_endpoint->ep_portlist;
2509 if (portlist->port_id == port_id)
2511 portlist = portlist->next;
2515 PERROR("EPOINT(%d) software error: no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2518 if (message_type != MESSAGE_RELEASE)
2520 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2521 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2522 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2523 message_put(message);
2524 logmessage(message);
2526 ea_endpoint->free_portlist(portlist);
2527 return; /* one relation removed */
2529 if (e_multipoint_cause)
2531 cause = e_multipoint_cause;
2532 location = e_multipoint_location;
2535 cause = param->disconnectinfo.cause;
2536 location = param->disconnectinfo.location;
2539 e_cfnr_call = e_cfnr_release = 0;
2541 /* process hangup */
2542 process_hangup(e_call_cause, e_call_location);
2543 e_multipoint_cause = 0;
2544 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
2546 /* tone to disconnected end */
2547 SPRINT(buffer, "cause_%02x", cause);
2548 if (ea_endpoint->ep_portlist)
2549 set_tone(ea_endpoint->ep_portlist, buffer);
2551 new_state(EPOINT_STATE_IN_DISCONNECT);
2552 if (ea_endpoint->ep_call_id)
2554 int haspatterns = 0;
2555 /* check if pattern is available */
2556 if (ea_endpoint->ep_portlist)
2557 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->earlyb)
2558 #warning wie ist das bei einem asterisk, gibts auch tones?
2559 if (callpbx_countrelations(ea_endpoint->ep_call_id)==2 // we must count relations, in order not to disturb the conference ; NOTE:
2560 && message_type != MESSAGE_RELEASE) // if we release, we are done
2564 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2565 /* indicate patterns */
2566 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2567 message_put(message);
2568 /* connect audio, if not already */
2569 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2570 message->param.channel = CHANNEL_STATE_CONNECT;
2571 message_put(message);
2572 /* send disconnect */
2573 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2574 memcpy(&message->param, param, sizeof(union parameter));
2575 message_put(message);
2576 /* disable encryption if disconnected */
2577 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2579 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2583 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2586 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2587 return; /* must exit here */
2590 /* port MESSAGE_TIMEOUT */
2591 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2595 trace_header("TIMEOUT", DIRECTION_IN);
2596 message_type = MESSAGE_DISCONNECT;
2597 switch (param->state)
2599 case PORT_STATE_OUT_SETUP:
2600 case PORT_STATE_OUT_OVERLAP:
2601 add_trace("state", NULL, "outgoing setup/dialing");
2603 /* no user responding */
2604 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2605 return; /* must exit here */
2607 case PORT_STATE_IN_SETUP:
2608 case PORT_STATE_IN_OVERLAP:
2609 add_trace("state", NULL, "incoming setup/dialing");
2610 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2611 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2614 case PORT_STATE_OUT_PROCEEDING:
2615 add_trace("state", NULL, "outgoing proceeding");
2617 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2618 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2619 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2620 return; /* must exit here */
2622 case PORT_STATE_IN_PROCEEDING:
2623 add_trace("state", NULL, "incoming proceeding");
2624 param->disconnectinfo.cause = CAUSE_NOUSER;
2625 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2628 case PORT_STATE_OUT_ALERTING:
2629 add_trace("state", NULL, "outgoing alerting");
2631 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2632 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2633 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2634 return; /* must exit here */
2636 case PORT_STATE_IN_ALERTING:
2637 add_trace("state", NULL, "incoming alerting");
2638 param->disconnectinfo.cause = CAUSE_NOANSWER;
2639 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2642 case PORT_STATE_IN_DISCONNECT:
2643 case PORT_STATE_OUT_DISCONNECT:
2644 add_trace("state", NULL, "disconnect");
2646 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2647 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2648 return; /* must exit here */
2651 param->disconnectinfo.cause = 31; /* normal unspecified */
2652 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2655 /* release call, disconnect isdn */
2657 new_state(EPOINT_STATE_OUT_DISCONNECT);
2658 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2659 SCPY(e_tone, cause);
2662 set_tone(portlist, cause);
2663 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2664 portlist = portlist->next;
2666 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
2669 /* port MESSAGE_NOTIFY */
2670 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2672 struct message *message;
2676 /* signal to call tool */
2677 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2678 if (param->notifyinfo.notify)
2680 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2683 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2684 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2686 case INFO_NOTIFY_REMOTE_HOLD:
2687 case INFO_NOTIFY_USER_SUSPENDED:
2688 /* tell call about it */
2689 if (ea_endpoint->ep_call_id)
2691 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2692 message->param.channel = CHANNEL_STATE_HOLD;
2693 message_put(message);
2697 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2698 case INFO_NOTIFY_USER_RESUMED:
2699 /* set volume of rx and tx */
2700 if (param->setup.callerinfo.itype == INFO_ITYPE_INTERN)
2701 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2704 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2705 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2706 message->param.mISDNsignal.rxvol = e_ext.txvol;
2707 message->param.mISDNsignal.txvol = e_ext.rxvol;
2708 message_put(message);
2710 /* set current tone */
2712 set_tone(portlist, e_tone);
2713 /* tell call about it */
2714 if (ea_endpoint->ep_call_id)
2716 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2717 message->param.channel = CHANNEL_STATE_CONNECT;
2718 message_put(message);
2723 /* get name of notify */
2724 switch(param->notifyinfo.notify)
2730 logtext = "USER_SUSPENDED";
2733 logtext = "BEARER_SERVICE_CHANGED";
2736 logtext = "USER_RESUMED";
2739 logtext = "CONFERENCE_ESTABLISHED";
2742 logtext = "CONFERENCE_DISCONNECTED";
2745 logtext = "OTHER_PARTY_ADDED";
2748 logtext = "ISOLATED";
2751 logtext = "REATTACHED";
2754 logtext = "OTHER_PARTY_ISOLATED";
2757 logtext = "OTHER_PARTY_REATTACHED";
2760 logtext = "OTHER_PARTY_SPLIT";
2763 logtext = "OTHER_PARTY_DISCONNECTED";
2766 logtext = "CONFERENCE_FLOATING";
2769 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2772 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2775 logtext = "CALL_IS_A_WAITING_CALL";
2778 logtext = "DIVERSION_ACTIVATED";
2781 logtext = "RESERVED_CT_1";
2784 logtext = "RESERVED_CT_2";
2787 logtext = "REVERSE_CHARGING";
2790 logtext = "REMOTE_HOLD";
2793 logtext = "REMOTE_RETRIEVAL";
2796 logtext = "CALL_IS_DIVERTING";
2799 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2803 trace_header("NOTIFY", DIRECTION_IN);
2804 if (param->notifyinfo.notify)
2805 add_trace("indicator", NULL, "%s", logtext);
2806 if (param->notifyinfo.id)
2808 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype));
2809 if (param->notifyinfo.present == INFO_PRESENT_RESTRICTED)
2810 add_trace("redir'on", "present", "restricted");
2812 if (param->notifyinfo.display[0])
2813 add_trace("display", NULL, "%s", param->notifyinfo.display);
2816 /* notify call if available */
2817 if (ea_endpoint->ep_call_id)
2819 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOTIFY);
2820 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2821 message_put(message);
2826 /* port MESSAGE_FACILITY */
2827 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2829 struct message *message;
2831 trace_header("FACILITY", DIRECTION_IN);
2834 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_FACILITY);
2835 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2836 message_put(message);
2839 /* port MESSAGE_SUSPEND */
2840 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2841 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2843 trace_header("SUSPEND", DIRECTION_IN);
2845 /* epoint is now parked */
2846 ea_endpoint->ep_park = 1;
2847 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2848 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2850 /* remove port relation */
2851 ea_endpoint->free_portlist(portlist);
2854 /* port MESSAGE_RESUME */
2855 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2856 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2858 trace_header("RESUME", DIRECTION_IN);
2860 /* epoint is now resumed */
2861 ea_endpoint->ep_park = 0;
2866 /* port sends message to the endpoint
2868 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2870 struct port_list *portlist;
2871 struct message *message;
2874 portlist = ea_endpoint->ep_portlist;
2877 if (port_id == portlist->port_id)
2879 portlist = portlist->next;
2883 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) warning: port is not related to this endpoint. This may happen, if port has been released after the message was created.\n", ea_endpoint->ep_serial);
2887 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2888 switch(message_type)
2890 case MESSAGE_DATA: /* data from port */
2891 /* send back to source for recording */
2894 message = message_create(ea_endpoint->ep_serial, port_id, EPOINT_TO_PORT, message_type);
2895 memcpy(&message->param, param, sizeof(union parameter));
2896 message_put(message);
2899 /* check if there is a call */
2900 if (!ea_endpoint->ep_call_id)
2902 /* continue if only one portlist */
2903 if (ea_endpoint->ep_portlist->next != NULL)
2905 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2906 memcpy(&message->param, param, sizeof(union parameter));
2907 message_put(message);
2910 case MESSAGE_TONE_EOF: /* tone is end of file */
2911 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2914 if (e_action->index == ACTION_VBOX_PLAY)
2918 if (e_action->index == ACTION_EFI)
2925 case MESSAGE_TONE_COUNTER: /* counter info received */
2926 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received counter information: %d / %d seconds after start of tone.\n", ea_endpoint->ep_serial, param->counter.current, param->counter.max);
2928 if (e_action->index == ACTION_VBOX_PLAY)
2930 e_vbox_counter = param->counter.current;
2931 if (param->counter.max >= 0)
2932 e_vbox_counter_max = param->counter.max;
2936 /* PORT sends SETUP message */
2938 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call from callerid=%s, dialing=%s\n", ea_endpoint->ep_serial, param->setup.callerinfo.id, param->setup.dialinginfo.number);
2939 if (e_state!=EPOINT_STATE_IDLE)
2941 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2944 port_setup(portlist, message_type, param);
2947 /* PORT sends INFORMATION message */
2948 case MESSAGE_INFORMATION: /* additional digits received */
2949 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call dialing more=%s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->information.number, e_ext.number, e_callerinfo.id);
2950 port_information(portlist, message_type, param);
2953 /* PORT sends FACILITY message */
2954 case MESSAGE_FACILITY:
2955 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2956 port_facility(portlist, message_type, param);
2959 /* PORT sends DTMF message */
2960 case MESSAGE_DTMF: /* dtmf digits received */
2961 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf digit=%c (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->dtmf, e_ext.number, e_callerinfo.id);
2962 port_dtmf(portlist, message_type, param);
2965 /* PORT sends CRYPT message */
2966 case MESSAGE_CRYPT: /* crypt response received */
2967 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2968 port_crypt(portlist, message_type, param);
2971 /* PORT sends MORE message */
2972 case MESSAGE_OVERLAP:
2973 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is accepted [overlap dialing] (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2974 if (e_state != EPOINT_STATE_OUT_SETUP)
2976 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state (for port_list: another portlist might have changed the state already).\n", ea_endpoint->ep_serial);
2979 port_overlap(portlist, message_type, param);
2982 /* PORT sends PROCEEDING message */
2983 case MESSAGE_PROCEEDING: /* port is proceeding */
2984 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is proceeding (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2985 if (e_state!=EPOINT_STATE_OUT_SETUP
2986 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2988 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in overlap state (for port_list: another portlist might have changed the state already).\n", ea_endpoint->ep_serial);
2991 port_proceeding(portlist, message_type, param);
2994 /* PORT sends ALERTING message */
2995 case MESSAGE_ALERTING:
2996 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is ringing (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2997 if (e_state!=EPOINT_STATE_OUT_SETUP
2998 && e_state!=EPOINT_STATE_OUT_OVERLAP
2999 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
3001 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state (for port_list: another portlist might have changed the state already).\n", ea_endpoint->ep_serial);
3004 port_alerting(portlist, message_type, param);
3007 /* PORT sends CONNECT message */
3008 case MESSAGE_CONNECT:
3009 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call connected to %s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_connectinfo.id, e_ext.number, e_callerinfo.id);
3010 if (e_state!=EPOINT_STATE_OUT_SETUP
3011 && e_state!=EPOINT_STATE_OUT_OVERLAP
3012 && e_state!=EPOINT_STATE_OUT_PROCEEDING
3013 && e_state!=EPOINT_STATE_OUT_ALERTING)
3015 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3018 port_connect(portlist, message_type, param);
3021 /* PORT sends DISCONNECT message */
3022 case MESSAGE_DISCONNECT: /* port is disconnected */
3023 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call disconnect with cause=%d location=%d (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->disconnectinfo.cause, param->disconnectinfo.location, e_ext.number, e_callerinfo.id);
3024 port_disconnect_release(portlist, message_type, param);
3027 /* PORT sends a RELEASE message */
3028 case MESSAGE_RELEASE: /* port releases */
3029 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) release with cause=%d location=%d (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->disconnectinfo.cause, param->disconnectinfo.location, e_ext.number, e_callerinfo.id);
3030 /* portlist is release at port_disconnect_release, thanx Paul */
3031 port_disconnect_release(portlist, message_type, param);
3034 /* PORT sends a TIMEOUT message */
3035 case MESSAGE_TIMEOUT:
3036 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received timeout (state=%d).\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->state);
3037 port_timeout(portlist, message_type, param);
3038 break; /* release */
3040 /* PORT sends a NOTIFY message */
3041 case MESSAGE_NOTIFY:
3042 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3043 port_notify(portlist, message_type, param);
3046 /* PORT sends a SUSPEND message */
3047 case MESSAGE_SUSPEND:
3048 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received suspend.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3049 port_suspend(portlist, message_type, param);
3050 break; /* suspend */
3052 /* PORT sends a RESUME message */
3053 case MESSAGE_RESUME:
3054 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received resume.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3055 port_resume(portlist, message_type, param);
3059 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message);
3062 /* Note: this endpoint may be destroyed, so we MUST return */
3066 /* messages from port
3068 /* call MESSAGE_CRYPT */
3069 void EndpointAppPBX::call_crypt(struct port_list *portlist, int message_type, union parameter *param)
3071 switch(param->crypt.type)
3073 /* message from remote port to "crypt manager" */
3074 case CU_ACTK_REQ: /* activate key-exchange */
3075 case CU_ACTS_REQ: /* activate shared key */
3076 case CU_DACT_REQ: /* deactivate */
3077 case CU_INFO_REQ: /* request last info message */
3078 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
3081 /* message from "crypt manager" to user */
3082 case CU_ACTK_CONF: /* key-echange done */
3083 case CU_ACTS_CONF: /* shared key done */
3084 case CU_DACT_CONF: /* deactivated */
3085 case CU_DACT_IND: /* deactivated */
3086 case CU_ERROR_IND: /* receive error message */
3087 case CU_INFO_IND: /* receive info message */
3088 case CU_INFO_CONF: /* receive info message */
3089 encrypt_result(param->crypt.type, (char *)param->crypt.data);
3093 PERROR("EPOINT(%d) epoint with terminal '%s' (caller id '%s') unknown crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
3097 /* call MESSAGE_INFORMATION */
3098 void EndpointAppPBX::call_information(struct port_list *portlist, int message_type, union parameter *param)
3100 struct message *message;
3106 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3107 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
3108 message_put(message);
3109 logmessage(message);
3110 portlist = portlist->next;
3114 /* call MESSAGE_FACILITY */
3115 void EndpointAppPBX::call_facility(struct port_list *portlist, int message_type, union parameter *param)
3117 struct message *message;
3119 if (!e_ext.facility)
3126 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
3127 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
3128 message_put(message);
3129 logmessage(message);
3130 portlist = portlist->next;
3134 /* call MESSAGE_MORE */
3135 void EndpointAppPBX::call_overlap(struct port_list *portlist, int message_type, union parameter *param)
3137 struct message *message;
3139 new_state(EPOINT_STATE_IN_OVERLAP);
3142 if (e_call_pattern && e_ext.own_setup)
3144 /* disconnect audio */
3145 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3146 message->param.channel = CHANNEL_STATE_HOLD;
3147 message_put(message);
3149 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3151 set_tone(portlist, "dialtone");
3154 if (e_ext.number[0])
3155 set_tone(portlist, "dialpbx");
3157 set_tone(portlist, "dialtone");
3160 /* call MESSAGE_PROCEEDING */
3161 void EndpointAppPBX::call_proceeding(struct port_list *portlist, int message_type, union parameter *param)
3163 struct message *message;
3165 new_state(EPOINT_STATE_IN_PROCEEDING);
3167 /* own proceeding tone */
3170 /* connect / disconnect audio */
3171 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3172 if (e_ext.own_proceeding)
3173 message->param.channel = CHANNEL_STATE_HOLD;
3175 message->param.channel = CHANNEL_STATE_CONNECT;
3176 message_put(message);
3178 // UCPY(e_call_tone, "proceeding");
3181 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3182 message_put(message);
3183 logmessage(message);
3185 set_tone(portlist, "proceeding");
3188 /* call MESSAGE_ALERTING */
3189 void EndpointAppPBX::call_alerting(struct port_list *portlist, int message_type, union parameter *param)
3191 struct message *message;
3193 new_state(EPOINT_STATE_IN_ALERTING);
3195 /* own alerting tone */
3198 /* connect / disconnect audio */
3199 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3200 if (e_ext.own_alerting)
3201 message->param.channel = CHANNEL_STATE_HOLD;
3203 message->param.channel = CHANNEL_STATE_CONNECT;
3204 message_put(message);
3208 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
3209 message_put(message);
3210 logmessage(message);
3212 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3214 set_tone(portlist, "ringing");
3217 if (e_ext.number[0])
3218 set_tone(portlist, "ringpbx");
3220 set_tone(portlist, "ringing");
3223 /* call MESSAGE_CONNECT */
3224 void EndpointAppPBX::call_connect(struct port_list *portlist, int message_type, union parameter *param)
3226 struct message *message;
3228 new_state(EPOINT_STATE_CONNECT);
3229 // UCPY(e_call_tone, "");
3230 if (e_ext.number[0])
3231 e_dtmf = 1; /* allow dtmf */
3233 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
3236 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3237 memcpy(&message->param, param, sizeof(union parameter));
3238 /* screen incoming caller id */
3239 screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present);
3240 memcpy(&message->param.connnectinfo, e_connectinfo);
3242 /* screen clip if prefix is required */
3243 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3245 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3246 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
3247 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3250 /* use internal caller id */
3251 if (e_ext.number[0] && e_connectinfo.intern[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3253 SCPY(message->param.connectinfo.id, e_connectinfo.intern);
3254 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3257 /* handle restricted caller ids */
3258 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);
3259 /* display callerid if desired for extension */
3260 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));
3262 /* use conp, if enabld */
3264 message->param.connectinfo.name[0] = '\0';
3267 message_put(message);
3268 logmessage(message);
3270 set_tone(portlist, NULL);
3272 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3273 message->param.channel = CHANNEL_STATE_CONNECT;
3274 message_put(message);
3278 /* call MESSAGE_DISCONNECT MESSAGE_RELEASE */
3279 void EndpointAppPBX::call_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
3282 struct message *message;
3285 /* be sure that we are active */
3287 e_tx_state = NOTIFY_STATE_ACTIVE;
3289 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3290 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3292 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
3294 /* set time for power dialing */
3295 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3298 /* set redial tone */
3299 if (ea_endpoint->ep_portlist)
3303 set_tone(ea_endpoint->ep_portlist, "redial");
3304 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') redialing in %d seconds\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (int)e_powerdelay);
3305 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3306 if (e_state==EPOINT_STATE_IN_OVERLAP)
3308 new_state(EPOINT_STATE_IN_PROCEEDING);
3311 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3312 message_put(message);
3313 logmessage(message);
3315 /* caused the error, that the first knock sound was not there */
3316 /* set_tone(portlist, "proceeding"); */
3318 /* send display of powerdialing */
3319 if (e_ext.display_dialing)
3323 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3325 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3327 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3328 message_put(message);
3329 logmessage(message);
3330 portlist = portlist->next;
3339 if ((e_state!=EPOINT_STATE_CONNECT
3340 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3341 && e_state!=EPOINT_STATE_IN_OVERLAP
3342 && e_state!=EPOINT_STATE_IN_PROCEEDING
3343 && e_state!=EPOINT_STATE_IN_ALERTING)
3344 || !ea_endpoint->ep_portlist) /* or no port */
3346 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3347 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, call, port */
3348 return; /* must exit here */
3353 e_call_cause = param->disconnectinfo.cause;
3354 e_call_location = param->disconnectinfo.location;
3357 /* on release we need the audio again! */
3358 if (message_type == MESSAGE_RELEASE)
3361 ea_endpoint->ep_call_id = 0;
3363 /* disconnect and select tone */
3364 new_state(EPOINT_STATE_OUT_DISCONNECT);
3365 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3366 /* if own_cause, we must release the call */
3367 if (e_ext.own_cause /* own cause */
3368 || !e_call_pattern) /* no patterns */
3370 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have own cause or we have no patterns. (own_cause=%d pattern=%d)\n", ea_endpoint->ep_serial, e_ext.own_cause, e_call_pattern);
3371 if (message_type != MESSAGE_RELEASE)
3372 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
3374 } else /* else we enable audio */
3376 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3377 message->param.channel = CHANNEL_STATE_CONNECT;
3378 message_put(message);
3380 /* send disconnect message */
3381 SCPY(e_tone, cause);
3384 set_tone(portlist, cause);
3385 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3386 portlist = portlist->next;
3390 /* call MESSAGE_SETUP */
3391 void EndpointAppPBX::call_setup(struct port_list *portlist, int message_type, union parameter *param)
3393 struct message *message;
3395 /* if we already in setup state, we just update the dialing with new digits */
3396 if (e_state == EPOINT_STATE_OUT_SETUP
3397 || e_state == EPOINT_STATE_OUT_OVERLAP)
3399 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3400 /* if digits changed, what we have already dialed */
3401 if (!!strncmp(e_dialinginfo.number,param->setup.dialinginfo.number,strlen(e_dialinginfo.number)))
3403 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have dialed digits which have been changed or we have a new multidial, so we must redial.\n", ea_endpoint->ep_serial);
3404 /* release all ports */
3405 while((portlist = ea_endpoint->ep_portlist))
3407 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3408 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3409 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3410 message_put(message);
3411 logmessage(message);
3412 ea_endpoint->free_portlist(portlist);
3415 /* disconnect audio */
3416 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3417 message->param.channel = CHANNEL_STATE_HOLD;
3418 message_put(message);
3420 /* get dialing info */
3421 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3422 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3423 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3424 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3425 new_state(EPOINT_STATE_OUT_OVERLAP);
3428 e_redial = now_d + 1; /* set redial one second in the future */
3431 /* if we have a pending redial, so we just adjust the dialing number */
3434 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) redial in progress, so we update the dialing number to %s.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.number);
3435 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3438 if (!ea_endpoint->ep_portlist)
3440 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3442 if (ea_endpoint->ep_portlist->next)
3444 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3446 if (e_state == EPOINT_STATE_OUT_SETUP)
3449 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) digits '%s' are queued because we didn't receive a setup acknowledge.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.number);
3450 SCAT(e_dialing_queue, param->setup.dialinginfo.number + strlen(e_dialinginfo.number));
3454 /* get what we have not dialed yet */
3455 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have already dialed '%s', we received '%s', what's left '%s'.\n", ea_endpoint->ep_serial, e_dialinginfo.number, param->setup.dialinginfo.number, param->setup.dialinginfo.number+strlen(e_dialinginfo.number));
3456 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3457 SCPY(message->param.information.number, param->setup.dialinginfo.number + strlen(e_dialinginfo.number));
3458 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3459 message_put(message);
3460 logmessage(message);
3462 /* always store what we have dialed or queued */
3463 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3467 if (e_state != EPOINT_STATE_IDLE)
3469 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3472 /* if an internal extension is dialed, copy that number */
3473 if (param->setup.dialinginfo.itype==INFO_ITYPE_INTERN || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3474 SCPY(e_ext.number, param->setup.dialinginfo.number);
3475 /* if an internal extension is dialed, get extension's info about caller */
3476 if (e_ext.number[0])
3478 if (!read_extension(&e_ext, e_ext.number))
3480 e_ext.number[0] = '\0';
3481 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3485 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3486 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3487 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3488 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3490 /* screen incoming caller id */
3491 screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present);
3493 /* process (voice over) data calls */
3494 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3496 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3497 memset(&e_capainfo, 0, sizeof(e_capainfo));
3498 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3499 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3500 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3503 new_state(EPOINT_STATE_OUT_SETUP);
3504 /* call special setup routine */
3508 /* call MESSAGE_mISDNSIGNAL */
3509 void EndpointAppPBX::call_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3511 struct message *message;
3515 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3516 memcpy(&message->param, param, sizeof(union parameter));
3517 message_put(message);
3518 portlist = portlist->next;
3522 /* call MESSAGE_NOTIFY */
3523 void EndpointAppPBX::call_notify(struct port_list *portlist, int message_type, union parameter *param)
3525 struct message *message;
3528 if (param->notifyinfo.notify)
3530 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3531 // /* if notification was generated locally, we turn hold music on/off */
3532 // if (param->notifyinfo.local)
3533 // NOTE: we always assume that we send hold music on suspension of call, because we don't track if audio is available or not (we assume that we always have no audio, to make it easier)
3538 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3542 set_tone(portlist, "");
3543 portlist = portlist->next;
3545 portlist = ea_endpoint->ep_portlist;
3550 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3554 set_tone(portlist, "hold");
3555 portlist = portlist->next;
3557 portlist = ea_endpoint->ep_portlist;
3562 /* save new state */
3563 e_tx_state = new_state;
3566 /* notify port(s) about it */
3569 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3570 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3571 /* handle restricted caller ids */
3572 apply_callerid_restriction(e_ext.anon_ignore, portlist->port_type, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, NULL, message->param.notifyinfo.voip, message->param.notifyinfo.intern, 0);
3573 /* display callerid if desired for extension */
3574 SCPY(message->param.notifyinfo.display, apply_callerid_display(message->param.notifyinfo.id, message->param.notifyinfo.itype, message->param.notifyinfo.ntype, message->param.notifyinfo.present, 0, message->param.notifyinfo.voip, message->param.notifyinfo.intern, NULL));
3575 message_put(message);
3576 logmessage(message);
3577 portlist = portlist->next;
3581 /* call sends messages to the endpoint
3583 void EndpointAppPBX::ea_message_call(unsigned long call_id, int message_type, union parameter *param)
3585 struct port_list *portlist;
3586 struct message *message;
3590 PERROR("EPOINT(%d) error: call == NULL.\n", ea_endpoint->ep_serial);
3594 portlist = ea_endpoint->ep_portlist;
3596 /* send MESSAGE_DATA to port */
3597 if (call_id == ea_endpoint->ep_call_id)
3599 if (message_type == MESSAGE_DATA)
3601 /* skip if no port relation */
3604 /* skip if more than one port relation */
3607 /* send audio data to port */
3608 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DATA);
3609 memcpy(&message->param, param, sizeof(union parameter));
3610 message_put(message);
3615 // PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active call (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
3616 switch(message_type)
3618 /* CALL SENDS CRYPT message */
3620 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
3621 call_crypt(portlist, message_type, param);
3624 /* CALL sends INFORMATION message */
3625 case MESSAGE_INFORMATION:
3626 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received more digits: '%s'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->information.number);
3627 call_information(portlist, message_type, param);
3630 /* CALL sends FACILITY message */
3631 case MESSAGE_FACILITY:
3632 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received facility\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3633 call_facility(portlist, message_type, param);
3636 /* CALL sends OVERLAP message */
3637 case MESSAGE_OVERLAP:
3638 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received 'more info available'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3639 if (e_state!=EPOINT_STATE_IN_SETUP
3640 && e_state!=EPOINT_STATE_IN_OVERLAP)
3642 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3645 call_overlap(portlist, message_type, param);
3648 /* CALL sends PROCEEDING message */
3649 case MESSAGE_PROCEEDING:
3650 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s (caller id '%s') received proceeding\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3651 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3653 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3656 call_proceeding(portlist, message_type, param);
3659 /* CALL sends ALERTING message */
3660 case MESSAGE_ALERTING:
3661 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received alerting\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3662 if (e_state!=EPOINT_STATE_IN_OVERLAP
3663 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3665 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3668 call_alerting(portlist, message_type, param);
3671 /* CALL sends CONNECT message */
3672 case MESSAGE_CONNECT:
3673 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received connect\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3674 if (e_state!=EPOINT_STATE_IN_OVERLAP
3675 && e_state!=EPOINT_STATE_IN_PROCEEDING
3676 && e_state!=EPOINT_STATE_IN_ALERTING)
3678 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3681 call_connect(portlist, message_type, param);
3684 /* CALL sends DISCONNECT/RELEASE message */
3685 case MESSAGE_DISCONNECT: /* call disconnect */
3686 case MESSAGE_RELEASE: /* call releases */
3687 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received %s with cause %d location %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (message_type==MESSAGE_DISCONNECT)?"disconnect":"release", param->disconnectinfo.cause, param->disconnectinfo.location);
3688 call_disconnect_release(portlist, message_type, param);
3691 /* CALL sends SETUP message */
3693 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received setup from terminal='%s',id='%s' to id='%s' (dialing itype=%d)\n", ea_endpoint->ep_serial, param->setup.callerinfo.intern, param->setup.callerinfo.id, param->setup.dialinginfo.number, param->setup.dialinginfo.itype);
3694 call_setup(portlist, message_type, param);
3698 /* CALL sends special mISDNSIGNAL message */
3699 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3700 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received mISDNsignal message.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3701 call_mISDNsignal(portlist, message_type, param);
3704 /* CALL has pattern available */
3705 case MESSAGE_PATTERN: /* indicating pattern available */
3706 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern availability.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3707 if (!e_call_pattern)
3709 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3714 set_tone(portlist, NULL);
3715 portlist = portlist->next;
3717 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3718 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3719 message->param.channel = CHANNEL_STATE_CONNECT;
3720 message_put(message);
3721 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3722 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_REMOTE_AUDIO);
3723 // message->param.channel = CHANNEL_STATE_CONNECT;
3724 // message_put(message);
3725 // patterns are available, remote already connected audio
3729 /* CALL has no pattern available */
3730 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3731 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern NOT available.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3734 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3736 /* disconnect our audio tx and rx */
3737 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3738 message->param.channel = CHANNEL_STATE_HOLD;
3739 message_put(message);
3744 /* CALL (dunno at the moment) */
3745 case MESSAGE_REMOTE_AUDIO:
3746 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received audio remote request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3747 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3748 message->param.channel = param->channel;
3749 message_put(message);
3753 /* CALL sends a notify message */
3754 case MESSAGE_NOTIFY:
3755 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3756 call_notify(portlist, message_type, param);
3760 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: #%d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message);
3765 /* pick_call will connect the first incoming call found. the endpoint
3766 * will receivce a MESSAGE_CONNECT.
3768 int match_list(char *list, char *item)
3770 char *end, *next = NULL;
3772 /* no list make matching */
3778 /* eliminate white spaces */
3779 while (*list <= ' ')
3786 /* if end of list is reached, we return */
3787 if (list[0] == '\0')
3789 /* if we have more than one entry (left) */
3790 if ((end = strchr(list, ',')))
3793 next = end = strchr(list, '\0');
3794 while (*(end-1) <= ' ')
3796 /* if string part matches item */
3797 if (!strncmp(list, item, end-list))
3803 void EndpointAppPBX::pick_call(char *extensions)
3805 struct message *message;
3806 struct port_list *portlist;
3808 class EndpointAppPBX *eapp, *found;
3810 class CallPBX *callpbx;
3811 struct call_relation *relation;
3814 /* find an endpoint that is ringing internally or vbox with higher priority */
3817 eapp = apppbx_first;
3820 if (eapp!=this && ea_endpoint->ep_portlist)
3822 portlist = eapp->ea_endpoint->ep_portlist;
3825 if ((port = find_port_id(portlist->port_id)))
3827 if (port->p_type == PORT_TYPE_VBOX_OUT)
3829 if (match_list(extensions, eapp->e_ext.number))
3836 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3837 && port->p_state==PORT_STATE_OUT_ALERTING)
3838 if (match_list(extensions, eapp->e_ext.number))
3843 portlist = portlist->next;
3851 /* if no endpoint found */
3854 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) nobody is ringing internally (or we don't have her in the access list), so we disconnect.\n", ea_endpoint->ep_serial);
3856 set_tone(ea_endpoint->ep_portlist, "cause_10");
3857 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3858 new_state(EPOINT_STATE_OUT_DISCONNECT);
3863 if (ea_endpoint->ep_call_id)
3865 PERROR("EPOINT(%d) we already have a call. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3868 if (!eapp->ea_endpoint->ep_call_id)
3870 PERROR("EPOINT(%d) ringing endpoint has no call.\n", ea_endpoint->ep_serial);
3873 call = find_call_id(eapp->ea_endpoint->ep_call_id);
3876 PERROR("EPOINT(%d) ringing endpoint's call not found.\n", ea_endpoint->ep_serial);
3879 if (callpbx->c_type != CALL_TYPE_PBX)
3881 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's call is not a PBX call, so we must reject.\n", ea_endpoint->ep_serial);
3884 callpbx = (class CallPBX *)call;
3885 relation = callpbx->c_relation;
3888 PERROR("EPOINT(%d) ringing endpoint's call has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3891 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3893 relation = relation->next;
3896 PERROR("EPOINT(%d) ringing endpoint's call has no relation to that call. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3901 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3903 if (options.deb & DEBUG_EPOINT)
3905 class Call *debug_c = call_first;
3906 class Endpoint *debug_e = epoint_first;
3907 class Port *debug_p = port_first;
3909 callpbx_debug(callpbx, "EndpointAppPBX::pick_call(before)");
3911 PDEBUG(DEBUG_EPOINT, "showing all calls:\n");
3914 PDEBUG(DEBUG_EPOINT, "call=%ld\n", debug_c->c_serial);
3915 debug_c = debug_c->next;
3917 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3920 PDEBUG(DEBUG_EPOINT, "ep=%ld, call=%ld\n", debug_e->ep_serial, debug_e->ep_call_id);
3921 debug_e = debug_e->next;
3923 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3926 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3927 debug_p = debug_p->next;
3932 ea_endpoint->ep_call_id = eapp->ea_endpoint->ep_call_id; /* we get the call */
3933 relation->epoint_id = ea_endpoint->ep_serial; /* the call gets us */
3934 eapp->ea_endpoint->ep_call_id = 0; /* the ringing endpoint will get disconnected */
3936 /* connnecting our endpoint */
3937 new_state(EPOINT_STATE_CONNECT);
3939 set_tone(ea_endpoint->ep_portlist, NULL);
3941 /* now we send a release to the ringing endpoint */
3942 message = message_create(ea_endpoint->ep_call_id, eapp->ea_endpoint->ep_serial, CALL_TO_EPOINT, MESSAGE_RELEASE);
3943 message->param.disconnectinfo.cause = 26; /* non selected user clearing */
3944 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3945 message_put(message);
3947 /* we send a connect to the call with our caller id */
3948 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CONNECT);
3949 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3950 message->param.connectinfo.present = e_callerinfo.present;
3951 message->param.connectinfo.screen = e_callerinfo.screen;
3952 message->param.connectinfo.itype = e_callerinfo.itype;
3953 message->param.connectinfo.ntype = e_callerinfo.ntype;
3954 message_put(message);
3956 /* we send a connect to our port with the remote callerid */
3957 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3958 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3959 message->param.connectinfo.present = eapp->e_callerinfo.present;
3960 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3961 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3962 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3963 /* handle restricted caller ids */
3964 apply_callerid_restriction(e_ext.anon_ignore, ea_endpoint->ep_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);
3965 /* display callerid if desired for extension */
3966 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));
3967 message_put(message);
3969 /* we send a connect to the audio path (not for vbox) */
3970 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3971 message->param.channel = CHANNEL_STATE_CONNECT;
3972 message_put(message);
3974 /* beeing paranoid, we make call update */
3975 callpbx->c_mixer = 1;
3977 if (options.deb & DEBUG_EPOINT)
3979 class Call *debug_c = call_first;
3980 class Endpoint *debug_e = epoint_first;
3981 class Port *debug_p = port_first;
3983 callpbx_debug(callpbx, "EndpointAppPBX::pick_call(after)");
3985 PDEBUG(DEBUG_EPOINT, "showing all calls:\n");
3988 PDEBUG(DEBUG_EPOINT, "call=%ld\n", debug_c->c_serial);
3989 debug_c = debug_c->next;
3991 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3994 PDEBUG(DEBUG_EPOINT, "ep=%ld, call=%ld\n", debug_e->ep_serial, debug_e->ep_call_id);
3995 debug_e = debug_e->next;
3997 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
4000 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
4001 debug_p = debug_p->next;
4007 /* join calls (look for a call that is on hold (same isdn interface/terminal))
4009 void EndpointAppPBX::join_call(void)
4011 struct message *message;
4012 struct call_relation *our_relation, *other_relation;
4013 struct call_relation **our_relation_pointer, **other_relation_pointer;
4014 class Call *our_call, *other_call;
4015 class CallPBX *our_callpbx, *other_callpbx;
4016 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
4017 class Port *our_port, *other_port;
4018 class Pdss1 *our_pdss1, *other_pdss1;
4020 /* are we a candidate to join a call */
4021 our_call = find_call_id(ea_endpoint->ep_call_id);
4024 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our call doesn't exist anymore.\n", ea_endpoint->ep_serial);
4027 if (our_call->c_type != CALL_TYPE_PBX)
4029 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: call is not a pbx call.\n", ea_endpoint->ep_serial);
4032 our_callpbx = (class CallPBX *)our_call;
4033 if (!ea_endpoint->ep_portlist)
4035 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
4038 if (!e_ext.number[0])
4040 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
4043 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
4046 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
4049 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
4051 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
4054 our_pdss1 = (class Pdss1 *)our_port;
4056 /* find an endpoint that is on hold and has the same mISDNport that we are on */
4057 other_eapp = apppbx_first;
4060 if (other_eapp == this)
4062 other_eapp = other_eapp->next;
4065 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint candiate: (ep%d) terminal='%s' port=%s call=%d.\n", ea_endpoint->ep_serial, other_eapp->ea_endpoint->ep_serial, other_eapp->e_ext.number, (other_eapp->ea_endpoint->ep_portlist)?"YES":"NO", other_eapp->ea_endpoint->ep_call_id);
4066 if (other_eapp->e_ext.number[0] /* has terminal */
4067 && other_eapp->ea_endpoint->ep_portlist /* has port */
4068 && other_eapp->ea_endpoint->ep_call_id) /* has call */
4070 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
4071 if (other_port) /* port still exists */
4073 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
4074 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
4076 other_pdss1 = (class Pdss1 *)other_port;
4077 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of type isdn! comparing our portnum=%d with other's portnum=%d hold=%s ces=%d\n", ea_endpoint->ep_serial, our_pdss1->p_m_mISDNport->portnum, other_pdss1->p_m_mISDNport->portnum, (other_pdss1->p_m_hold)?"YES":"NO", other_pdss1->p_m_d_ces);
4078 if (other_pdss1->p_m_hold /* port is on hold */
4079 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
4080 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
4084 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
4088 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
4091 other_eapp = other_eapp->next;
4095 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
4098 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
4100 /* if we have the same call */
4101 if (other_eapp->ea_endpoint->ep_call_id == ea_endpoint->ep_call_id)
4103 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same call.\n", ea_endpoint->ep_serial);
4106 other_call = find_call_id(other_eapp->ea_endpoint->ep_call_id);
4109 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other call doesn't exist anymore.\n", ea_endpoint->ep_serial);
4112 if (other_call->c_type != CALL_TYPE_PBX)
4114 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other call is not a pbx call.\n", ea_endpoint->ep_serial);
4117 other_callpbx = (class CallPBX *)other_call;
4118 if (our_callpbx->c_partyline && other_callpbx->c_partyline)
4120 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both calls are partylines.\n", ea_endpoint->ep_serial);
4124 /* remove relation to endpoint for call on hold */
4125 other_relation = other_callpbx->c_relation;
4126 other_relation_pointer = &other_callpbx->c_relation;
4127 while(other_relation)
4129 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
4131 /* detach other endpoint on hold */
4132 *other_relation_pointer = other_relation->next;
4133 memset(other_relation, 0, sizeof(struct call_relation));
4134 free(other_relation);
4136 other_relation = *other_relation_pointer;
4137 other_eapp->ea_endpoint->ep_call_id = NULL;
4141 /* change call/hold pointer of endpoint to the new call */
4142 temp_epoint = find_epoint_id(other_relation->epoint_id);
4145 if (temp_epoint->ep_call_id == other_call->c_serial)
4146 temp_epoint->ep_call_id = our_call->c_serial;
4149 other_relation_pointer = &other_relation->next;
4150 other_relation = other_relation->next;
4152 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on call relinked (to our call).\n", ea_endpoint->ep_serial);
4154 /* join call relations */
4155 our_relation = our_callpbx->c_relation;
4156 our_relation_pointer = &our_callpbx->c_relation;
4159 our_relation_pointer = &our_relation->next;
4160 our_relation = our_relation->next;
4162 *our_relation_pointer = other_callpbx->c_relation;
4163 other_callpbx->c_relation = NULL;
4164 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
4166 /* release endpoint on hold */
4167 message = message_create(other_callpbx->c_serial, other_eapp->ea_endpoint->ep_serial, CALL_TO_EPOINT, MESSAGE_RELEASE);
4168 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
4169 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
4170 message_put(message);
4172 /* if we are not a partyline, we get partyline state from other call */
4173 our_callpbx->c_partyline += other_callpbx->c_partyline;
4175 /* remove empty call */
4177 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-call completely removed!\n");
4179 /* mixer must update */
4180 our_callpbx->c_mixer = 1; /* update mixer flag */
4182 /* we send a retrieve to that endpoint */
4183 // mixer will update the hold-state of the call and send it to the endpoints is changes
4187 /* check if we have an external call
4188 * this is used to check for encryption ability
4190 int EndpointAppPBX::check_external(char **errstr, class Port **port)
4192 struct call_relation *relation;
4194 class CallPBX *callpbx;
4195 class Endpoint *epoint;
4197 /* some paranoia check */
4198 if (!ea_endpoint->ep_portlist)
4200 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4201 *errstr = "No Call";
4204 if (!e_ext.number[0])
4206 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4207 *errstr = "No Call";
4211 /* check if we have a call with 2 parties */
4212 call = find_call_id(ea_endpoint->ep_call_id);
4215 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no call.\n", ea_endpoint->ep_serial);
4216 *errstr = "No Call";
4219 if (call->c_type != CALL_TYPE_PBX)
4221 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call is nto a pbx call.\n", ea_endpoint->ep_serial);
4222 *errstr = "No PBX Call";
4225 callpbx = (class CallPBX *)call;
4226 relation = callpbx->c_relation;
4229 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no relation.\n", ea_endpoint->ep_serial);
4230 *errstr = "No Call";
4233 if (!relation->next)
4235 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no 2nd relation.\n", ea_endpoint->ep_serial);
4236 *errstr = "No Call";
4239 if (relation->next->next)
4241 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has more than two relations.\n", ea_endpoint->ep_serial);
4242 *errstr = "Err: Conference";
4245 if (relation->epoint_id == ea_endpoint->ep_serial)
4247 relation = relation->next;
4248 if (relation->epoint_id == ea_endpoint->ep_serial)
4250 PERROR("EPOINT(%d) SOFTWARE ERROR: both call relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4251 *errstr = "Software Error";
4256 /* check remote port for external call */
4257 epoint = find_epoint_id(relation->epoint_id);
4260 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4261 *errstr = "No Call";
4264 if (!epoint->ep_portlist)
4266 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4267 *errstr = "No Call";
4270 *port = find_port_id(epoint->ep_portlist->port_id);
4273 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4274 *errstr = "No Call";
4277 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4279 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4280 *errstr = "No Ext Call";
4283 if ((*port)->p_state != PORT_STATE_CONNECT)
4285 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4286 *errstr = "No Ext Connect";
4292 void EndpointAppPBX::logmessage(struct message *message)
4296 char *logtext = "unknown";
4299 if (message->flow != EPOINT_TO_PORT)
4301 PERROR("EPOINT(%d) message not of correct flow type-\n", ea_endpoint->ep_serial);
4305 switch(message->type)
4308 trace_header("SETUP", DIRECTION_OUT);
4309 if (message->param.setup.callerinfo.intern[0])
4310 add_trace("extension", NULL, "%s", message->param.setup.callerinfo.intern);
4311 add_trace("caller id", "number", "%s", numberrize_callerinfo(message->param.setup.callerinfo.id, message->param.setup.callerinfo.ntype));
4312 if (message->param.setup.callerinfo.present == INFO_PRESENT_RESTRICTED)
4313 add_trace("caller id", "present", "restricted");
4314 if (message->param.setup.redirinfo.number[0])
4316 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(message->param.setup.redirinfo.id, message->param.setup.redirinfo.ntype));
4317 if (message->param.setup.redirinfo.present == INFO_PRESENT_RESTRICTED)
4318 add_trace("redir'ing", "present", "restricted");
4320 if (message->param.setup.dialinginfo.number[0])
4321 add_trace("dialing", NULL, "%s", message->param.setup.dialinginfo.number);
4325 case MESSAGE_OVERLAP:
4326 trace_header("SETUP ACKNOWLEDGE", DIRECTION_OUT);
4330 case MESSAGE_PROCEEDING:
4331 trace_header("PROCEEDING", DIRECTION_OUT);
4335 case MESSAGE_ALERTING:
4336 trace_header("ALERTING", DIRECTION_OUT);
4340 case MESSAGE_CONNECT:
4341 trace_header("CONNECT", DIRECTION_OUT);
4342 if (message->param.connectinfo.intern[0])
4343 add_trace("extension", NULL, "%s", message->param.connectinfo.intern);
4344 add_trace("connect id", "number", "%s", numberrize_callerinfo(message->param.connectinfo.id, message->param.connectinfo.ntype));
4345 if (message->param.connectinfo.present == INFO_PRESENT_RESTRICTED)
4346 add_trace("connect id", "present", "restricted");
4350 case MESSAGE_DISCONNECT:
4351 trace_header("DISCONNECT", DIRECTION_OUT);
4352 add_trace("cause", "value", "%d", message->param.disconnectinfo.cause);
4353 add_trace("cause", "location", "%d", message->param.disconnectinfo.location);
4357 case MESSAGE_RELEASE:
4358 trace_header("RELEASE", DIRECTION_OUT);
4359 add_trace("cause", "value", "%d", message->param.disconnectinfo.cause);
4360 add_trace("cause", "location", "%d", message->param.disconnectinfo.location);
4364 case MESSAGE_NOTIFY:
4365 switch(message->param.notifyinfo.notify)
4371 logtext = "USER_SUSPENDED";
4374 logtext = "BEARER_SERVICE_CHANGED";
4377 logtext = "USER_RESUMED";
4380 logtext = "CONFERENCE_ESTABLISHED";
4383 logtext = "CONFERENCE_DISCONNECTED";
4386 logtext = "OTHER_PARTY_ADDED";
4389 logtext = "ISOLATED";
4392 logtext = "REATTACHED";
4395 logtext = "OTHER_PARTY_ISOLATED";
4398 logtext = "OTHER_PARTY_REATTACHED";
4401 logtext = "OTHER_PARTY_SPLIT";
4404 logtext = "OTHER_PARTY_DISCONNECTED";
4407 logtext = "CONFERENCE_FLOATING";
4410 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4413 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4416 logtext = "CALL_IS_A_WAITING_CALL";
4419 logtext = "DIVERSION_ACTIVATED";
4422 logtext = "RESERVED_CT_1";
4425 logtext = "RESERVED_CT_2";
4428 logtext = "REVERSE_CHARGING";
4431 logtext = "REMOTE_HOLD";
4434 logtext = "REMOTE_RETRIEVAL";
4437 logtext = "CALL_IS_DIVERTING";
4440 SPRINT(buffer, "%d", message->param.notifyinfo.notify - 0x80);
4444 trace_header("NOTIFY", DIRECTION_OUT);
4445 if (message->param.notifyinfo.notify)
4446 add_trace("indicator", NULL, "%s", logtext);
4447 if (message->param.notifyinfo.number[0])
4449 add_trace("redir'on", "number", "%s", numberrize_callerinfo(message->param.notifyinfo.id, message->param.notifyinfo.ntype));
4450 if (message->param.notifyinfo.present == INFO_PRESENT_RESTRICTED)
4451 add_trace("redir'on", "present", "restricted");
4453 if (message->param.notifyinfo.display[0])
4454 add_trace("display", NULL, "%s", message->param.notifyinfo.display);
4458 case MESSAGE_INFORMATION:
4459 trace_header("INFORMATION", DIRECTION_OUT);
4460 add_trace("dialing", NULL, "%s", message->param.information.number);
4464 case MESSAGE_FACILITY:
4465 trace_header("FACILITY", DIRECTION_OUT);
4470 trace_header("TONE", DIRECTION_OUT);
4471 if (message->param.tone.name[0])
4473 add_trace("directory", NULL, "%s", message->param.tone.dir[0]?message->param.tone.dir:"default");
4474 add_trace("name", NULL, "%s", message->param.tone.name);
4476 add_trace("off", NULL, NULL);
4481 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message->type);
4485 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4487 struct message *message;
4491 if (!portlist->port_id)
4494 if (!e_connectedmode)
4496 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4497 message->param.disconnectinfo.cause = cause;
4498 message->param.disconnectinfo.location = location;
4500 SCPY(message->param.disconnectinfo.display, display);
4502 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4505 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4507 SCPY(message->param.notifyinfo.display, display);
4509 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4511 message_put(message);
4512 logmessage(message);