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;
46 e_terminal_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");
140 /* set new endpoint state
142 void EndpointAppPBX::new_state(int state)
144 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new state %s --> %s\n", ea_endpoint->ep_serial, state_name[e_state], state_name[state]);
150 * out==0: incomming caller id, out==1: outgoing caller id
152 void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present)
154 struct interface *interface;
156 interface = interface_first;
159 if (!strcmp(e_callerinfo.interface, interface->name))
163 interface = interface->next;
168 /* screen incoming caller id */
171 /* check for MSN numbers, use first MSN if no match */
173 ifmsn = interface->ifmsn;
178 if (!strcmp(ifmns->mns, id))
184 if (!ifmns && mns1) // not in list, first msn given
185 UNCPY(id, msn1, idsize);
189 /* check screen list */
191 iscreen = interface->ifscreen_out;
193 iscreen = interface->ifscreen_in;
196 if (ifcreen->match_type==-1 || ifscreen->match_type==*type)
197 if (ifcreen->match_present==-1 || ifscreen->match_present==*present)
199 if (strchr(ifcreen->match_id,'%'))
201 if (!strncmp(ifscreen->match_id, id, strchr(ifscreen->match_id,'%')-ifscreen->match_id))
205 if (!strcmp(ifscreen->match_id, id))
209 ifscreen = ifscreen->next;
211 if (ifscreen) // match
213 if (ifscren->result_type != -1)
214 *type = ifscreen->result_type;
215 if (ifscren->result_present != -1)
216 *present = ifscreen->result_present;
217 if (strchr(ifscreen->match_id,'%'))
219 SCPY(suffix, strchr(ifscreen->match_id,'%') - ifscreen->match_id + id);
220 UNCPY(id, ifscreen->result_id);
222 if (strchr(ifscreen->result_id,'%'))
224 *strchr(ifscreen->result_id,'%') = '\0';
225 UNCAT(id, suffix, idsize);
230 UNCPY(id, ifscreen->result_id, idsize);
237 /* release call and port (as specified)
239 void EndpointAppPBX::release(int release, int calllocation, int callcause, int portlocation, int portcause)
241 struct port_list *portlist;
242 struct message *message;
246 /* message to test call */
247 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", callcause, calllocation, 0);
249 /* if a release is pending */
250 if (release==RELEASE_CALL || release==RELEASE_ALL || release==RELEASE_PORT_CALLONLY)
252 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (callcause %d location %d)\n", ea_endpoint->ep_serial, callcause, calllocation);
253 if (ea_endpoint->ep_call_id)
255 call = find_call_id(ea_endpoint->ep_call_id);
257 call->release(ea_endpoint->ep_serial, 0, calllocation, callcause);
259 ea_endpoint->ep_call_id = 0;
262 if (release != RELEASE_PORT_CALLONLY)
265 call_release(e_hold_id, ea_endpoint->ep_serial, 1, calllocation, callcause);
270 if (release==RELEASE_ALL || release==RELEASE_PORT_CALLONLY)
272 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
273 while((portlist = ea_endpoint->ep_portlist))
275 if (portlist->port_id)
277 SPRINT(cause, "cause_%02x", portcause);
278 set_tone(portlist, cause);
279 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
280 message->param.disconnectinfo.cause = portcause;
281 message->param.disconnectinfo.location = portlocation;
282 message_put(message);
285 ea_endpoint->free_portlist(portlist);
288 /* if callback is enabled, call back with the given caller id */
291 /* reset some stuff */
292 new_state(EPOINT_STATE_IDLE);
293 memset(&e_connectinfo, 0, sizeof(struct connect_info));
294 memset(&e_redirinfo, 0, sizeof(struct redir_info));
295 e_start = e_stop = 0;
296 e_ruleset = ruleset_main;
298 e_rule = e_ruleset->rule_first;
300 e_action_timeout = 0;
302 e_match_to_action = NULL;
304 e_extdialing = e_dialinginfo.number;
311 e_multipoint_cause = CAUSE_NOUSER;
312 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
313 e_dialing_queue[0] = '\0';
315 e_crypt_state = CM_ST_NULL;
316 e_crypt_keyengine_busy = 0;
317 e_crypt_info[0] = '\0';
321 e_tx_state = NOTIFY_STATE_ACTIVE;
322 e_rx_state = NOTIFY_STATE_ACTIVE;
323 e_call_cause = e_call_location = 0;
325 /* the caller info of the callback user */
326 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
327 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
328 /* create dialing by callerinfo */
329 if (e_terminal[0] && e_terminal_interface[0])
331 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_terminal, e_terminal_interface);
332 /* create callback to the current terminal */
333 SCPY(e_dialinginfo.number, e_terminal);
334 SCPY(e_dialinginfo.interfaces, e_terminal_interface);
335 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
336 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
341 SCPY(e_dialinginfo.number, e_cbto);
344 /* numberrize caller id and use it to dial to the callback */
345 SCPY(e_dialinginfo.number, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
347 e_dialinginfo.itype = INFO_ITYPE_ISDN;
348 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
349 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.number);
354 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
355 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
361 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
362 void apply_callerid_restriction(int anon_ignore, int port_type, char *id, int *ntype, int *present, int *screen, char *voip, char *intern, char *name)
364 PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d voip='%s' intern='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (voip)?voip:"NULL", (intern)?intern:"NULL", (name)?name:"NULL");
366 /* caller id is not restricted, so we do nothing */
367 if (*present != INFO_PRESENT_RESTRICTED)
370 /* only extensions are restricted */
376 /* if we enabled anonymouse ignore */
380 /* else we remove the caller id */
384 *ntype = INFO_NTYPE_UNKNOWN;
386 // *screen = INFO_SCREEN_USER;
387 // maybe we should not make voip address anonymous
390 // maybe it's no fraud to present internal id
397 /* used display message to display callerid as available */
398 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *voip, char *intern, char *name)
400 static char display[81];
403 char *cid = numberrize_callerinfo(id, ntype);
405 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d voip='%s' intern='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (voip)?voip:"NULL", (intern)?intern:"NULL", (name)?name:"NULL");
416 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
418 /* internal extension's caller id */
419 if (intern[0] && e_ext.display_int)
422 SCAT(display, intern);
425 if (itype == INFO_ITYPE_VBOX)
426 SCAT(display, "(vbox)");
428 SCAT(display, "(int)");
431 /* external caller id */
432 if (!intern[0] && !voip[0] && e_ext.display_ext)
438 if (present == INFO_PRESENT_RESTRICTED)
439 SCAT(display, "anonymous");
441 SCAT(display, "unknown");
449 if (voip[0] && e_ext.display_voip)
451 if (!display[0] && cid[0])
458 /* display if callerid is anonymouse but available due anon-ignore */
459 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
462 SCAT(display, "unknown");
465 SCAT(display, " anon");
468 /* display if callerid is anonymouse but available due anon-ignore */
469 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
475 if (present == INFO_PRESENT_RESTRICTED)
476 SCAT(display, "anonymous");
478 SCAT(display, "unknown");
483 SCAT(display, " fake");
487 if (name[0] && e_ext.display_name)
489 if (!display[0] && cid[0])
500 * uses the current state to notify activity
502 void EndpointAppPBX::notify_active(void)
504 struct port_list *portlist = ea_endpoint->ep_portlist;
505 struct message *message;
510 case NOTIFY_STATE_ACTIVE:
511 /* we are already active, so we don't do anything */
514 case NOTIFY_STATE_SUSPEND:
515 notify = INFO_NOTIFY_USER_RESUMED;
518 set_tone(portlist, NULL);
519 portlist = portlist->next;
521 portlist = ea_endpoint->ep_portlist;
524 case NOTIFY_STATE_HOLD:
525 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
528 set_tone(portlist, NULL);
529 portlist = portlist->next;
531 portlist = ea_endpoint->ep_portlist;
534 case NOTIFY_STATE_CONFERENCE:
535 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
538 set_tone(portlist, NULL);
539 portlist = portlist->next;
541 portlist = ea_endpoint->ep_portlist;
545 PERROR("unknown e_tx_state = %d\n", e_tx_state);
551 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
552 message->param.notifyinfo.notify = notify;
553 message_put(message);
555 portlist = portlist->next;
561 * keypad functions during call. one example to use this is to put a call on hold or start a conference
563 void EndpointAppPBX::keypad_function(char digit)
566 /* we must be in a call, in order to send messages to the call */
567 if (e_terminal[0] == '\0')
569 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
575 /* join conference */
577 if (ea_endpoint->ep_call_id == 0)
579 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
582 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
588 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
592 /* crypt key-exchange */
594 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
600 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
605 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
610 /* set tone pattern for port */
611 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
613 struct message *message;
618 /* store for suspended processes */
623 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no endpoint to notify tone.\n", ea_endpoint->ep_serial);
627 if (e_call_pattern /* pattern are provided */
628 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
629 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
630 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
631 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
632 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
633 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
634 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
635 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
636 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
637 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
638 && tone[0] && !!strncmp(tone,"crypt_*",6))
640 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
646 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
647 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
648 SCPY(message->param.tone.name, tone);
649 message_put(message);
656 * hunts an mISDNport that is available for an outgoing call
657 * if no ifname was given, any interface that is not an extension
660 static struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
662 struct interface *interface;
663 struct mISDNport *mISDNport;
665 interface = interface_first;
667 /* first find the given interface or, if not given, one with no extension */
672 /* check for given interface */
675 if (!strcasecmp(interface->name, ifname))
677 /* found explicit interface */
678 printlog("%3d interface %s found as given\n", ea_endpoint->ep_serial, ifname);
684 if (!interface->extension)
686 /* found non extension */
687 printlog("%3d interface %s found, that is not an extension\n", ea_endpoint->ep_serial, interface->name);
692 interface = interface->next;
695 /* see if interface has ports */
696 if (!interface->ifport)
699 printlog("%3d interface %s has no active ports, skipping.\n", ea_endpoint->ep_serial, interface->name);
700 interface = interface->next;
704 /* select port by algorithm */
705 ifport_start = interface->port;
707 if (interface->hunt == HUNT_ROUNDROBIN)
709 while(ifport_start->next && index<interface->hunt_next)
711 ifport_start = ifport_start->next;
714 printlog("%3d starting with port#%d position %d (round-robin)\n", ea_endpoint->ep_serial, ifport_start->portnum, index);
718 ifport = ifport_start;
721 /* see if port is available */
722 if (!ifport->mISDNport)
724 printlog("%3d port#%d position %d is not available, skipping.\n", ea_endpoint->ep_serial, ifport->portnum, index);
727 mISDNport = ifport->mISDNport;
729 #warning admin block auch bei incomming calls
730 #warning calls releasen, wenn port entfernt wird, geblockt wird
731 /* see if port is administratively blocked */
734 printlog("%3d port#%d position %d is administratively blocked, skipping.\n", ea_endpoint->ep_serial, ifport->portnum, index);
738 /* see if link is up */
739 if (mISDNport->ptp && !mISDNport->l2link)
741 printlog("%3d port#%d position %d is ptp but layer 2 is down.\n", ea_endpoint->ep_serial, ifport->portnum, index);
742 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is PTP with L2 down\n", ea_endpoint->ep_serial);
746 /* check for channel form selection list */
748 selchannel = ifport->selchannel;
751 switch(selchannel->channel)
753 case CHANNEL_FREE: /* free channel */
754 if (mISDNport->b_inuse >= mISDNport->b_num)
755 break; /* all channel in use or reserverd */
758 while(i < mISDNport->b_num)
760 if (mISDNport->b_port[i] == NULL)
762 *channel = i+1+(i>=15);
763 printlog("%3d port#%d position %d selecting free channel %d\n", ea_endpoint->ep_serial, ifport->portnum, index, *channel);
770 case CHANNEL_ANY: /* don't ask for channel */
771 if (mISDNport->b_inuse >= mISDNport->b_num)
773 break; /* all channel in use or reserverd */
775 printlog("%3d port#%d position %d using with 'any channel'\n", ea_endpoint->ep_serial, ifport->portnum, index);
776 *channel = SEL_CHANNEL_ANY;
779 case CHANNEL_NO: /* call waiting */
780 printlog("%3d port#%d position %d using with 'no channel'\n", ea_endpoint->ep_serial, ifport->portnum, index);
781 *channel = SEL_CHANNEL_NO;
785 if (selchannel->channel<1 || selchannel->channel==16)
786 break; /* invalid channels */
787 i = selchannel->channel-1-(selchannel->channel>=17);
788 if (i >= mISDNport->b_num)
789 break; /* channel not in port */
790 if (mISDNport->b_port[i] == NULL)
792 *channel = selchannel->channel;
793 printlog("%3d port#%d position %d selecting given channel %d\n", ea_endpoint->ep_serial, ifport->portnum, index, *channel);
799 break; /* found channel */
800 selchannel = selchannel->next;
803 /* if channel was found, return mISDNport and channel */
806 /* setting next port to start next time */
807 if (interface->hunt == HUNT_ROUNDROBIN)
812 interface->hunt_next = index;
818 printlog("%3d port#%d position %d skipping, because no channel found.\n", ea_endpoint->ep_serial, ifport->portnum, index);
821 /* go next port, until all ports are checked */
823 ifport = ifport->next;
827 ifport = interface->ifport;
829 if (ifport != ifport_start)
832 return(NULL); /* no port found */
835 /* outgoing setup to port(s)
836 * ports will be created and a setup is sent if everything is ok. otherwhise
837 * the endpoint is destroyed.
839 void EndpointAppPBX::out_setup(void)
841 struct dialing_info dialinginfo;
843 // class pdss1 *pdss1;
844 struct port_list *portlist;
845 struct message *message;
847 int cause = CAUSE_RESSOURCEUNAVAIL;
850 struct mISDNport *mISDNport;
853 class EndpointAppPBX *atemp;
854 // char allowed_ports[256];
858 char ifname[sizeof(e_ext.interfaces)],
860 struct port_settings port_settings;
863 /* create settings for creating port */
864 memset(&port_settings, 0, sizeof(port_settings));
866 SCPY(port_settings.tones_dir, e_ext.tones_dir);
868 SCPY(port_settings.tones_dir, options.tones_dir);
869 port_settings.tout_setup = e_ext.tout_setup;
870 port_settings.tout_dialing = e_ext.tout_dialing;
871 port_settings.tout_proceeding = e_ext.tout_proceeding;
872 port_settings.tout_alerting = e_ext.tout_alerting;
873 port_settings.tout_disconnect = e_ext.tout_disconnect;
874 // port_settings.tout_hold = e_ext.tout_hold;
875 // port_settings.tout_park = e_ext.tout_park;
876 port_settings.no_seconds = e_ext.no_seconds;
878 /* 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 */
880 /* check what dialinginfo.itype we got */
881 switch(e_dialinginfo.itype)
883 /* *********************** call to extension or vbox */
884 case INFO_ITYPE_ISDN_EXTENSION:
885 /* check if we deny incoming calls when we use an extension */
886 if (e_ext.noknocking)
888 atemp = apppbx_first;
892 if (!strcmp(atemp->e_terminal, e_terminal))
898 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
899 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ call, port */
900 return; /* must exit here */
903 /* FALL THROUGH !!!! */
904 case INFO_ITYPE_VBOX:
905 /* get dialed extension's info */
906 // SCPY(exten, e_dialinginfo.number);
907 // if (strchr(exten, ','))
908 // *strchr(exten, ',') = '\0';
909 // if (!read_extension(&e_ext, exten))
910 if (!read_extension(&e_ext, e_dialinginfo.number))
912 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.number);
913 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
914 return; /* must exit here */
917 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
919 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
924 /* string from unconditional call forward (cfu) */
928 /* present to forwarded party */
929 if (e_ext.anon_ignore && e_callerinfo.id[0])
931 e_callerinfo.present = INFO_PRESENT_ALLOWED;
933 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
937 /* string from busy call forward (cfb) */
941 class EndpointAppPBX *checkapp = apppbx_first;
944 if (checkapp != this) /* any other endpoint except our own */
946 if (!strcmp(checkapp->e_terminal, e_terminal))
948 /* present to forwarded party */
949 if (e_ext.anon_ignore && e_callerinfo.id[0])
951 e_callerinfo.present = INFO_PRESENT_ALLOWED;
953 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
957 checkapp = checkapp->next;
961 /* string from no-response call forward (cfnr) */
965 /* when cfnr is done, out_setup() will setup the call */
968 /* present to forwarded party */
969 if (e_ext.anon_ignore && e_callerinfo.id[0])
971 e_callerinfo.present = INFO_PRESENT_ALLOWED;
975 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
977 e_cfnr_release = now + e_ext.cfnr_delay;
978 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
979 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);
983 /* call to all internal interfaces */
984 p = e_ext.interfaces;
985 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple calls for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.number, p);
989 while(*p!=',' && *p!='\0')
994 /* found interface */
995 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
996 /* hunt for mISDNport and create Port */
997 mISDNport = hunt_port(ifname, &channel);
1000 printlog("%3d endpoint INTERFACE '%s' not found or busy\n", ea_endpoint->ep_serial, ifname);
1001 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) given interface: '%s' not found or too busy to accept calls.\n", ea_endpoint->ep_serial, e_ext.interfaces);
1004 /* creating INTERNAL port */
1005 SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
1006 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport.channel_force);
1009 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port '%s' failed to create\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1010 goto check_anycall_intern;
1012 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1013 memset(&dialinginfo, 0, sizeof(dialinginfo));
1014 SCPY(dialinginfo.number, e_dialinginfo.number);
1015 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1016 dialinginfo.ntype = e_dialinginfo.ntype;
1017 /* create port_list relation */
1018 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->is_earlyb);
1021 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1023 goto check_anycall_intern;
1025 /* directory.list */
1026 if (e_callerinfo.id[0] && (e_ext.centrex || e_ext.display_name))
1028 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1030 SCPY(e_callerinfo.name, dirname);
1032 // dss1 = (class Pdss1 *)port;
1034 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
1035 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1036 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1037 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1038 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1039 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1040 //terminal SCPY(message->param.setup.from_terminal, e_terminal);
1041 //terminal if (e_dialinginfo.number)
1042 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
1043 /* handle restricted caller ids */
1044 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);
1045 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);
1046 /* display callerid if desired for extension */
1047 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));
1048 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1049 /* use cnip, if enabld */
1051 message->param.setup.callerinfo.name[0] = '\0';
1052 /* screen clip if prefix is required */
1053 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1055 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1056 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
1057 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1059 /* use internal caller id */
1060 if (e_callerinfo.intern[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1062 SCPY(message->param.setup.callerinfo.id, e_callerinfo.intern);
1063 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1065 message_put(message);
1066 logmessage(message);
1070 /* string from parallel call forward (cfp) */
1074 if (e_ext.anon_ignore && e_callerinfo.id[0])
1076 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1080 vbox_only: /* entry point for answering machine only */
1081 cfu_only: /* entry point for cfu */
1082 cfb_only: /* entry point for cfb */
1083 cfnr_only: /* entry point for cfnr */
1084 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number, p);
1088 /* only if vbox should be dialed, and terminal is given */
1090 if (!strcmp(p, "vbox") && e_terminal[0])
1092 /* go to the end of p */
1095 /* answering vbox call */
1096 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1098 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1100 PERROR("EPOINT(%d) no mem for port\n", ea_endpoint->ep_serial);
1103 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1104 UCPY(cfp, e_terminal); /* cfp or any other direct forward/vbox */
1108 while(*p!=',' && *p!='\0')
1114 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1115 /* hunt for mISDNport and create Port */
1116 mISDNport = mISDNport_first;
1120 /* check for external or given interface */
1121 if (((!e_dialinginfo.interfaces[0])&&mISDNport->iftype==IF_EXTERN) || !strcmp(mISDNport->interface_name, e_dialinginfo.interfaces))
1123 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) interface '%s' found\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1124 cause = CAUSE_NOCHANNEL; /* when failing: out of channels */
1125 /* if PTP, skip all down links */
1126 if (mISDNport->ptp && !mISDNport->l2link)
1128 printlog("%3d endpoint INTERFACE Layer 2 of interface '%s' is down.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1129 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is PTP with L2 down\n", ea_endpoint->ep_serial);
1130 mISDNport = mISDNport->next;
1133 /* if no channel is available */
1134 if (mISDNport->multilink || !mISDNport->ntmode || mISDNport->ptp)
1138 ii = mISDNport->b_num;
1141 if (mISDNport->b_state[i])
1145 if (use >= mISDNport->b_num)
1147 printlog("%3d endpoint INTERFACE Interface '%s' has no free channel.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1148 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is not single link port_list NT-modem OR no channel available.\n", ea_endpoint->ep_serial);
1149 mISDNport = mISDNport->next;
1153 /* found interface */
1154 printlog("%3d endpoint INTERFACE Interface '%s' found for external call.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1157 mISDNport = mISDNport->next;
1161 /* creating EXTERNAL port*/
1162 SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
1163 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings);
1164 earlyb = mISDNport->is_earlyb;
1168 printlog("%3d endpoint INTERFACE External interface not found or busy.\n", ea_endpoint->ep_serial);
1169 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) given interface: '%s' too busy to accept calls.\n", ea_endpoint->ep_serial, e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1174 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1175 goto check_anycall_intern;
1177 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1178 memset(&dialinginfo, 0, sizeof(dialinginfo));
1179 SCPY(dialinginfo.number, cfp);
1180 dialinginfo.itype = INFO_ITYPE_EXTERN;
1181 dialinginfo.ntype = e_dialinginfo.ntype;
1182 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1185 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1187 goto check_anycall_intern;
1189 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
1190 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1191 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1192 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1193 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1194 /* if clip is hidden */
1195 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1197 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1198 SCPY(message->param.setup.callerinfo.intern, e_terminal);
1199 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1200 message->param.setup.callerinfo.present = e_ext.callerid_present;
1202 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1203 //terminal SCPY(message->param.setup.from_terminal, e_terminal);
1204 //terminal if (e_dialinginfo.number)
1205 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
1206 /* handle restricted caller ids */
1207 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);
1208 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);
1209 /* display callerid if desired for extension */
1210 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));
1211 message_put(message);
1212 logmessage(message);
1216 check_anycall_intern:
1217 /* now we have all ports created */
1220 printlog("%3d endpoint INTERFACE No port or no parallel forwarding defined. Nothing to call to.\n", ea_endpoint->ep_serial);
1221 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port or no cfp defined for extension, nothing to dial.\n", ea_endpoint->ep_serial);
1222 if (!ea_endpoint->ep_call_id)
1224 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1225 return; /* must exit here */
1229 /* *********************** external call */
1231 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number);
1232 /* call to extenal interfaces */
1233 p = e_dialinginfo.number;
1237 while(*p!=',' && *p!='\0')
1238 SCCAT(number, *p++);
1242 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");
1243 /* hunt for mISDNport and create Port */
1244 mISDNport = mISDNport_first;
1248 /* check for external or given interface */
1249 if ((!e_dialinginfo.interfaces[0]&&mISDNport->iftype==IF_EXTERN) || !strcmp(mISDNport->interface_name, e_dialinginfo.interfaces))
1251 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) interface '%s' found\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1252 cause = CAUSE_NOCHANNEL; /* when failing: out of channels */
1253 /* if PTP, skip all down links */
1254 if (mISDNport->ptp && !mISDNport->l2link)
1256 printlog("%3d endpoint INTERFACE Layer 2 of interface '%s' is down.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1257 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is PTP with L2 down\n", ea_endpoint->ep_serial);
1258 mISDNport = mISDNport->next;
1261 /* if no channel is available */
1262 if (mISDNport->multilink || !mISDNport->ntmode || mISDNport->ptp)
1266 ii = mISDNport->b_num;
1269 if (mISDNport->b_state[i])
1273 if (use >= mISDNport->b_num)
1275 printlog("%3d endpoint INTERFACE Interface '%s' has no free channel.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1276 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is not single link port_list NT-modem OR no channel available.\n", ea_endpoint->ep_serial);
1277 mISDNport = mISDNport->next;
1281 /* found interface */
1282 printlog("%3d endpoint INTERFACE Interface '%s' found for external call.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1285 mISDNport = mISDNport->next;
1289 printlog("%3d endpoint INTERFACE External interface not found or busy.\n", ea_endpoint->ep_serial);
1290 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) given interface: '%s' too busy to accept calls.\n", ea_endpoint->ep_serial, e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1291 goto check_anycall_extern;
1293 /* creating EXTERNAL port*/
1294 SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
1295 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings);
1298 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no external port available\n", ea_endpoint->ep_serial);
1299 goto check_anycall_extern;
1301 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1302 memset(&dialinginfo, 0, sizeof(dialinginfo));
1303 SCPY(dialinginfo.number, number);
1304 dialinginfo.itype = INFO_ITYPE_EXTERN;
1305 dialinginfo.ntype = e_dialinginfo.ntype;
1306 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->is_earlyb);
1309 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1311 goto check_anycall_extern;
1313 // dss1 = (class Pdss1 *)port;
1314 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
1315 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1316 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1317 SCPY(message->param.setup.dialinginfo.number, number);
1318 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1319 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1320 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1321 //terminal SCPY(message->param.setup.from_terminal, e_terminal);
1322 //terminal if (e_dialinginfo.number)
1323 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
1324 /* handle restricted caller ids */
1325 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);
1326 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);
1327 /* display callerid if desired for extension */
1328 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));
1329 message_put(message);
1330 logmessage(message);
1334 check_anycall_extern:
1335 /* now we have all ports created */
1338 printlog("%3d endpoint INTERFACE No free port found for making any call.\n", ea_endpoint->ep_serial);
1339 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found which is idle for at least one number\n", ea_endpoint->ep_serial);
1340 if (!ea_endpoint->ep_call_id)
1342 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1343 return; /* must exit here */
1351 /* handler for endpoint
1355 int EndpointAppPBX::handler(void)
1357 if (e_crypt_state!=CM_ST_NULL)
1362 /* process answering machine (play) handling */
1365 if (e_action->index == ACTION_VBOX_PLAY)
1368 /* process action timeout */
1369 if (e_action_timeout)
1370 if (now_d >= e_action_timeout)
1372 if (e_state!=EPOINT_STATE_CONNECT)
1375 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1376 e_multipoint_cause = CAUSE_NOUSER;
1377 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
1378 new_state(EPOINT_STATE_IN_OVERLAP);
1381 return(1); /* we must exit, because our endpoint might be gone */
1383 e_action_timeout = 0;
1386 /* process action timeout */
1387 if (e_match_timeout)
1388 if (now_d >= e_match_timeout)
1391 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1393 return(1); /* we must exit, because our endpoint might be gone */
1398 /* process redialing (epoint redials to port) */
1401 if (now_d >= e_redial)
1404 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1406 new_state(EPOINT_STATE_OUT_SETUP);
1407 /* call special setup routine */
1414 /* process powerdialing (epoint redials to epoint) */
1415 if (e_powerdialing > 0)
1417 if (now_d >= e_powerdialing)
1419 e_powerdialing = -1; /* leave power dialing on */
1420 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1423 e_ruleset = ruleset_main;
1425 e_rule = e_ruleset->rule_first;
1427 new_state(EPOINT_STATE_IN_OVERLAP);
1433 /* process call forward no response */
1436 struct port_list *portlist;
1437 struct message *message;
1439 if (now >= e_cfnr_release)
1441 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1444 /* release all ports */
1445 while((portlist = ea_endpoint->ep_portlist))
1447 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1448 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1449 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1450 message_put(message);
1451 logmessage(message);
1452 ea_endpoint->free_portlist(portlist);
1455 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
1456 message->param.channel = CHANNEL_STATE_HOLD;
1457 message_put(message);
1458 /* indicate no patterns */
1459 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
1460 message_put(message);
1461 /* set setup state, since we have no response from the new call */
1462 new_state(EPOINT_STATE_OUT_SETUP);
1467 if (now >= e_cfnr_call)
1469 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1475 /* handle connection to user */
1476 if (e_state == EPOINT_STATE_IDLE)
1478 /* epoint is idle, check callback */
1480 if (now_d >= e_callback)
1482 e_callback = 0; /* done with callback */
1483 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1484 new_state(EPOINT_STATE_OUT_SETUP);
1490 /* check for password timeout */
1492 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1494 struct port_list *portlist;
1496 if (now >= e_password_timeout)
1498 e_ruleset = ruleset_main;
1500 e_rule = e_ruleset->rule_first;
1502 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1503 printlog("%3d endpoint PASSWORD timeout\n", ea_endpoint->ep_serial);
1504 e_connectedmode = 0;
1506 new_state(EPOINT_STATE_OUT_DISCONNECT);
1507 portlist = ea_endpoint->ep_portlist;
1510 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1511 set_tone(portlist, "cause_10");
1521 /* doing a hookflash */
1522 void EndpointAppPBX::hookflash(void)
1526 /* be sure that we are active */
1528 e_tx_state = NOTIFY_STATE_ACTIVE;
1530 printlog("%3d endpoint HOOKFLASH\n", ea_endpoint->ep_serial);
1531 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf hookflash detected.\n", ea_endpoint->ep_serial);
1532 if (ea_endpoint->ep_use > 1)
1534 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1537 /* dialtone after pressing the hash key */
1538 process_hangup(e_call_cause, e_call_location);
1539 e_multipoint_cause = CAUSE_NOUSER;
1540 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
1541 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1544 port->set_echotest(0);
1546 if (ea_endpoint->ep_call_id)
1548 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1550 e_ruleset = ruleset_main;
1552 e_rule = e_ruleset->rule_first;
1554 new_state(EPOINT_STATE_IN_OVERLAP);
1555 e_connectedmode = 1;
1556 SCPY(e_dialinginfo.number, e_ext.prefix);
1557 e_extdialing = e_dialinginfo.number;
1559 if (e_dialinginfo.number[0])
1561 set_tone(ea_endpoint->ep_portlist, "dialing");
1565 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1572 /* messages from port
1574 /* port MESSAGE_SETUP */
1575 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1577 struct message *message;
1580 char extension1[32];
1582 int writeext; /* flags need to write extension after modification */
1585 portlist->port_type = param->setup.port_type;
1586 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1587 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1588 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1589 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1590 e_dtmf = param->setup.dtmf;
1592 /* screen by interface */
1593 if (e_callerinfo.interface[0])
1595 /* screen incoming caller id */
1596 screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present);
1598 colp, outclip, outcolp
1600 /* process extension */
1601 if (e_callerinfo.itype == INFO_ITYPE_INTERN)
1603 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1604 /* port makes call from extension */
1605 SCPY(e_callerinfo.intern, e_callerinfo.id);
1606 SCPY(e_terminal, e_callerinfo.intern);
1607 SCPY(e_terminal_interface, e_callerinfo.interface);
1610 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1612 printlog("%3d incoming %s='%s'%s%s%s%s dialing='%s'\n",
1613 ea_endpoint->ep_serial,
1614 (e_callerinfo.intern[0])?"SETUP from extension":"SETUP from extern",
1615 (e_callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
1616 (e_callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
1617 (e_redirinfo.id[0])?"redirected='":"",
1619 (e_redirinfo.id[0])?"'":"",
1620 e_dialinginfo.number
1623 if (e_callerinfo.itype == INFO_ITYPE_INTERN)
1625 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_terminal);
1627 /* get extension's info about caller */
1628 if (!read_extension(&e_ext, e_terminal))
1630 /* extension doesn't exist */
1631 printlog("%3d endpoint EXTENSION '%s' doesn't exist, please check or create.\n", ea_endpoint->ep_serial, e_callerinfo.id);
1632 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting call from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_terminal);
1633 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1634 new_state(EPOINT_STATE_OUT_DISCONNECT);
1635 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1636 e_terminal[0] = '\0'; /* no terminal */
1641 /* put prefix (next) in front of e_dialinginfo.number */
1644 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.number);
1645 SCPY(e_dialinginfo.number, buffer);
1646 e_ext.next[0] = '\0';
1648 } else if (e_ext.prefix[0])
1650 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.number);
1651 SCPY(e_dialinginfo.number, buffer);
1654 /* screen caller id */
1655 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1657 SCPY(e_callerinfo.name, e_ext.name);
1658 /* use caller id (or if exist: id_next_call) for this call */
1659 if (e_ext.id_next_call_present >= 0)
1661 SCPY(e_callerinfo.id, e_ext.id_next_call);
1662 /* if we restrict the pesentation */
1663 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1664 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1665 else e_callerinfo.present = e_ext.id_next_call_present;
1666 e_callerinfo.ntype = e_ext.id_next_call_type;
1667 e_ext.id_next_call_present = -1;
1671 SCPY(e_callerinfo.id, e_ext.callerid);
1672 /* if we restrict the pesentation */
1673 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1674 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1675 else e_callerinfo.present = e_ext.callerid_present;
1676 e_callerinfo.ntype = e_ext.callerid_type;
1679 /* extension is written */
1681 write_extension(&e_ext, e_terminal);
1683 /* set volume of rx and tx */
1684 if (param->setup.callerinfo.itype == INFO_ITYPE_INTERN)
1685 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
1687 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1688 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1689 message->param.mISDNsignal.rxvol = e_ext.txvol;
1690 message->param.mISDNsignal.txvol = e_ext.rxvol;
1691 message_put(message);
1694 /* start recording if enabled */
1695 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1697 /* check if we are a terminal */
1698 if (e_terminal[0] == '\0')
1699 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1702 port = find_port_id(portlist->port_id);
1704 port->open_record(e_ext.record, 0, 0, e_terminal, e_ext.anon_ignore, "", 0);
1709 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1710 /* no terminal identification */
1711 e_terminal[0] = '\0';
1712 e_terminal_interface[0] = '\0';
1713 memset(&e_ext, 0, sizeof(e_ext));
1714 e_ext.rights = 4; /* right to dial internat */
1718 e_ruleset = ruleset_main;
1720 e_rule = e_ruleset->rule_first;
1722 e_extdialing = e_dialinginfo.number;
1723 new_state(EPOINT_STATE_IN_SETUP);
1724 if (e_dialinginfo.number[0])
1726 set_tone(portlist, "dialing");
1730 set_tone(portlist, "dialpbx");
1732 set_tone(portlist, "dialtone");
1735 if (e_state == EPOINT_STATE_IN_SETUP)
1737 /* request MORE info, if not already at higher state */
1738 new_state(EPOINT_STATE_IN_OVERLAP);
1739 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1740 message_put(message);
1741 logmessage(message);
1745 /* port MESSAGE_INFORMATION */
1746 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1748 printlog("%3d incoming INFORMATION information='%s'\n",
1749 ea_endpoint->ep_serial,
1750 param->information.number
1754 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1757 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_terminal, e_callerinfo.id);
1761 /* if vbox_play is done, the information are just used as they come */
1763 if (e_action->index == ACTION_VBOX_PLAY)
1765 /* concat dialing string */
1766 SCAT(e_dialinginfo.number, param->information.number);
1771 /* keypad when disconnect but in connected mode */
1772 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1774 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.number);
1775 /* processing keypad function */
1776 if (param->information.number[0] == '0')
1783 /* keypad when connected */
1784 if (e_state == EPOINT_STATE_CONNECT && e_ext.keypad)
1786 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.number);
1787 /* processing keypad function */
1788 if (param->information.number[0] == '0')
1792 if (param->information.number[0])
1793 keypad_function(param->information.number[0]);
1796 if (e_state != EPOINT_STATE_IN_OVERLAP)
1798 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in overlap, or connect state.\n", ea_endpoint->ep_serial);
1801 if (!param->information.number[0])
1803 if (e_dialinginfo.number[0]=='\0' && !e_action)
1805 set_tone(portlist, "dialing");
1808 if (e_action->index==ACTION_OUTDIAL
1809 || e_action->index==ACTION_EXTERNAL)
1812 set_tone(portlist, "dialing");
1813 else if (!e_extdialing[0])
1814 set_tone(portlist, "dialing");
1816 /* concat dialing string */
1817 SCAT(e_dialinginfo.number, param->information.number);
1821 /* port MESSAGE_DTMF */
1822 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1824 printlog("%3d incoming DTMF digit='%c'\n",
1825 ea_endpoint->ep_serial,
1828 /* only if dtmf detection is enabled */
1831 PDEBUG(DEBUG_EPOINT, "dtmf detection is disabled\n");
1836 NOTE: vbox is now handled due to overlap state
1837 /* if vbox_play is done, the dtmf digits are just used as they come */
1839 if (e_action->index == ACTION_VBOX_PLAY)
1841 /* concat dialing string */
1842 if (strlen(e_dialinginfo.number)+1 < sizeof(e_dialinginfo.number))
1844 e_dialinginfo.number[strlen(e_dialinginfo.number)+1] = '\0';
1845 e_dialinginfo.number[strlen(e_dialinginfo.number)] = param->dtmf;
1848 /* continue to process *X# sequences */
1852 /* check for *X# sequence */
1853 if (e_state == EPOINT_STATE_CONNECT)
1855 if (e_dtmf_time+3 < now)
1857 /* the last digit was too far in the past to be a sequence */
1858 if (param->dtmf == '*')
1859 /* only start is allowed in the sequence */
1865 /* we have a sequence of digits, see what we got */
1866 if (param->dtmf == '*')
1868 else if (param->dtmf>='0' && param->dtmf<='9')
1870 /* we need to have a star before we receive the digit of the sequence */
1871 if (e_dtmf_last == '*')
1872 e_dtmf_last = param->dtmf;
1873 } else if (param->dtmf == '#')
1876 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1878 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1879 if (e_dtmf_last == '0')
1884 /* processing keypad function */
1886 keypad_function(e_dtmf_last);
1892 /* set last time of dtmf */
1897 /* check for ## hookflash during dialing */
1899 if (e_action->index==ACTION_PASSWORD
1900 || e_action->index==ACTION_PASSWORD_WRITE)
1902 if (param->dtmf=='#') /* current digit is '#' */
1904 if (e_state==EPOINT_STATE_IN_DISCONNECT
1905 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1922 /* dialing using dtmf digit */
1923 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1925 if (e_dialinginfo.number[0]=='\0' && !e_action)
1927 set_tone(portlist, "dialing");
1929 /* concat dialing string */
1930 if (strlen(e_dialinginfo.number)+1 < sizeof(e_dialinginfo.number))
1932 e_dialinginfo.number[strlen(e_dialinginfo.number)+1] = '\0';
1933 e_dialinginfo.number[strlen(e_dialinginfo.number)] = param->dtmf;
1939 /* port MESSAGE_CRYPT */
1940 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1942 /* send crypt response to cryptman */
1943 if (param->crypt.type == CR_MESSAGE_IND)
1944 cryptman_msg2man(param->crypt.data, param->crypt.len);
1946 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1949 /* port MESSAGE_OVERLAP */
1950 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1952 struct message *message;
1954 /* signal to call tool */
1955 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1957 printlog("%3d incoming SETUP ACKNOWLEDGE\n",
1958 ea_endpoint->ep_serial
1960 if (e_dialing_queue[0] && portlist)
1962 /* send what we have not dialed yet, because we had no setup complete */
1963 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1964 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1965 SCPY(message->param.information.number, e_dialing_queue);
1966 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1967 message_put(message);
1968 logmessage(message);
1969 e_dialing_queue[0] = '\0';
1971 /* check if pattern is available */
1972 if (!ea_endpoint->ep_portlist->next && portlist->earlyb) /* one port_list relation and tones available */
1974 /* indicate patterns */
1975 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
1976 message_put(message);
1978 /* connect audio, if not already */
1979 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
1980 message->param.channel = CHANNEL_STATE_CONNECT;
1981 message_put(message);
1984 /* indicate no patterns */
1985 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
1986 message_put(message);
1988 /* disconnect audio, if not already */
1989 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
1990 message->param.channel = CHANNEL_STATE_HOLD;
1991 message_put(message);
1993 new_state(EPOINT_STATE_OUT_OVERLAP);
1994 /* if we are in a call */
1995 if (ea_endpoint->ep_call_id)
1997 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
1998 memcpy(&message->param, param, sizeof(union parameter));
1999 message_put(message);
2003 /* port MESSAGE_PROCEEDING */
2004 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2006 struct message *message;
2008 /* signal to call tool */
2009 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
2011 printlog("%3d incoming PROCEEDING\n",
2012 ea_endpoint->ep_serial
2014 e_state = EPOINT_STATE_OUT_PROCEEDING;
2015 /* check if pattern is availatle */
2016 if (!ea_endpoint->ep_portlist->next && (portlist->earlyb || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2018 /* indicate patterns */
2019 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2020 message_put(message);
2022 /* connect audio, if not already */
2023 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2024 message->param.channel = CHANNEL_STATE_CONNECT;
2025 message_put(message);
2028 /* indicate no patterns */
2029 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
2030 message_put(message);
2032 /* disconnect audio, if not already */
2033 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2034 message->param.channel = CHANNEL_STATE_HOLD;
2035 message_put(message);
2037 /* if we are in a call */
2038 if (ea_endpoint->ep_call_id)
2040 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2041 memcpy(&message->param, param, sizeof(union parameter));
2042 message_put(message);
2046 /* port MESSAGE_ALERTING */
2047 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
2049 struct message *message;
2051 /* signal to call tool */
2052 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
2054 printlog("%3d incoming ALERTING\n",
2055 ea_endpoint->ep_serial
2057 new_state(EPOINT_STATE_OUT_ALERTING);
2058 /* check if pattern is available */
2059 if (!ea_endpoint->ep_portlist->next && (portlist->earlyb || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2061 /* indicate patterns */
2062 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2063 message_put(message);
2065 /* connect audio, if not already */
2066 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2067 message->param.channel = CHANNEL_STATE_CONNECT;
2068 message_put(message);
2071 /* indicate no patterns */
2072 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
2073 message_put(message);
2075 /* disconnect audio, if not already */
2076 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2077 message->param.channel = CHANNEL_STATE_HOLD;
2078 message_put(message);
2080 /* if we are in a call */
2081 if (ea_endpoint->ep_call_id)
2083 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2084 memcpy(&message->param, param, sizeof(union parameter));
2085 message_put(message);
2089 /* port MESSAGE_CONNECT */
2090 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2092 struct message *message;
2094 unsigned long port_id = portlist->port_id;
2095 struct port_list *tportlist;
2098 /* signal to call tool */
2099 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2101 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2102 printlog("%3d incoming CONNECT id='%s'%s\n",
2103 ea_endpoint->ep_serial,
2104 (e_connectinfo.intern[0])?e_connectinfo.intern:e_connectinfo.id,
2105 (e_connectinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":""
2107 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2108 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2110 tportlist = ea_endpoint->ep_portlist;
2111 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2112 tportlist = tportlist->next;
2113 if (tportlist->port_id == port_id)
2115 PERROR("EPOINT(%d) software error: this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2118 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2119 message->param.disconnectinfo.cause = 26; /* non selected user clearing */
2120 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2121 message_put(message);
2122 logmessage(message);
2123 ea_endpoint->free_portlist(tportlist);
2125 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2129 /* screen by interface */
2130 if (e_callerinfo.interface[0])
2132 /* screen incoming caller id */
2133 screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present);
2136 /* screen connected name */
2138 SCPY(e_connectinfo.name, e_ext.name);
2140 /* add internal id to colp */
2141 SCPY(e_connectinfo.intern, e_terminal);
2143 /* we store the connected port number */
2144 SCPY(e_terminal_interface, e_connectinfo.interfaces);
2146 /* for internal and am calls, we get the extension's id */
2147 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2149 SCPY(e_connectinfo.id, e_ext.callerid);
2150 SCPY(e_connectinfo.intern, e_terminal);
2151 e_connectinfo.itype = INFO_ITYPE_INTERN;
2152 e_connectinfo.ntype = e_ext.callerid_type;
2153 e_connectinfo.present = e_ext.callerid_present;
2155 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2157 e_connectinfo.itype = INFO_ITYPE_VBOX;
2158 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2161 new_state(EPOINT_STATE_CONNECT);
2163 /* set volume of rx and tx */
2164 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2166 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2167 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2168 message->param.mISDNsignal.rxvol = e_ext.txvol;
2169 message->param.mISDNsignal.txvol = e_ext.rxvol;
2170 message_put(message);
2173 e_cfnr_call = e_cfnr_release = 0;
2175 e_dtmf = 1; /* allow dtmf */
2176 // if (call_countrelations(ea_endpoint->ep_call_id) == 2)
2179 /* other calls with no caller id (or not available for the extension) and force colp */
2180 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2182 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2183 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2185 port = find_port_id(portlist->port_id);
2188 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.number, &e_connectinfo.ntype));
2189 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2193 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2194 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2195 message_put(message);
2197 if (ea_endpoint->ep_call_id)
2199 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2200 message->param.channel = CHANNEL_STATE_CONNECT;
2201 message_put(message);
2202 } else if (!e_adminid)
2205 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2206 SCPY(e_terminal, e_cbcaller);
2207 new_state(EPOINT_STATE_IN_OVERLAP);
2208 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_terminal);
2210 /* get extension's info about terminal */
2211 if (!read_extension(&e_ext, e_terminal))
2213 /* extension doesn't exist */
2214 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_terminal);
2215 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2216 new_state(EPOINT_STATE_OUT_DISCONNECT);
2217 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2221 /* put prefix in front of e_cbdialing */
2222 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2223 SCPY(e_dialinginfo.number, buffer);
2224 e_dialinginfo.itype = INFO_ITYPE_EXTERN;
2225 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2227 /* use caller id (or if exist: id_next_call) for this call */
2228 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2229 SCPY(e_callerinfo.intern, e_terminal);
2230 if (e_ext.id_next_call_present >= 0)
2232 SCPY(e_callerinfo.id, e_ext.id_next_call);
2233 e_callerinfo.present = e_ext.id_next_call_present;
2234 e_callerinfo.ntype = e_ext.id_next_call_type;
2235 e_ext.id_next_call_present = -1;
2236 /* extension is written */
2237 write_extension(&e_ext, e_terminal);
2240 SCPY(e_callerinfo.id, e_ext.callerid);
2241 e_callerinfo.present = e_ext.callerid_present;
2242 e_callerinfo.ntype = e_ext.callerid_type;
2245 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2248 /* check if caller id is NOT authenticated */
2249 if (!parse_callbackauth(e_terminal, &e_callbackinfo))
2251 /* make call state to enter password */
2252 new_state(EPOINT_STATE_IN_OVERLAP);
2253 e_action = &action_password_write;
2254 e_match_timeout = 0;
2255 e_match_to_action = NULL;
2256 e_dialinginfo.number[0] = '\0';
2257 e_extdialing = strchr(e_dialinginfo.number, '\0');
2258 e_password_timeout = now+20;
2262 /* incoming call (callback) */
2263 e_ruleset = ruleset_main;
2265 e_rule = e_ruleset->rule_first;
2267 e_extdialing = e_dialinginfo.number;
2268 if (e_dialinginfo.number[0])
2270 set_tone(portlist, "dialing");
2274 set_tone(portlist, "dialpbx");
2277 } else /* testcall */
2279 set_tone(portlist, "hold");
2282 /* start recording if enabled, not when answering machine answers */
2283 if (param->connectinfo.itype!=INFO_ITYPE_VBOX && e_terminal[0] && e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
2285 /* check if we are a terminal */
2286 if (e_terminal[0] == '\0')
2287 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2290 port = find_port_id(portlist->port_id);
2292 port->open_record(e_ext.record, 0, 0, e_terminal, e_ext.anon_ignore, "", 0);
2297 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2298 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2300 struct message *message;
2302 unsigned long port_id = portlist->port_id;
2306 /* signal to call tool */
2307 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2309 printlog("%3d incoming %s cause='%d' (%s) location='%d' (%s)\n",
2310 ea_endpoint->ep_serial,
2311 (message_type==MESSAGE_DISCONNECT)?"DISCONNECT":"RELEASE",
2312 param->disconnectinfo.cause,
2313 (param->disconnectinfo.cause>0 && param->disconnectinfo.cause<128)?isdn_cause[param->disconnectinfo.cause].english:"-",
2314 param->disconnectinfo.location,
2315 (param->disconnectinfo.location>=0 && param->disconnectinfo.location<16)?isdn_location[param->disconnectinfo.location].english:"-"
2318 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2319 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2321 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2326 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);
2327 if (param->disconnectinfo.cause == CAUSE_REJECTED) /* call rejected */
2329 e_multipoint_cause = CAUSE_REJECTED;
2330 e_multipoint_location = param->disconnectinfo.location;
2332 if (param->disconnectinfo.cause==CAUSE_NORMAL && e_multipoint_cause!=CAUSE_REJECTED) /* reject via hangup */
2334 e_multipoint_cause = CAUSE_NORMAL;
2335 e_multipoint_location = param->disconnectinfo.location;
2337 if (param->disconnectinfo.cause==CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* busy */
2339 e_multipoint_cause = CAUSE_BUSY;
2340 e_multipoint_location = param->disconnectinfo.location;
2342 if (param->disconnectinfo.cause==CAUSE_OUTOFORDER && e_multipoint_cause!=CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* no L1 */
2344 e_multipoint_cause = CAUSE_OUTOFORDER;
2345 e_multipoint_location = param->disconnectinfo.location;
2347 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 */
2349 e_multipoint_cause = param->disconnectinfo.cause;
2350 e_multipoint_location = param->disconnectinfo.location;
2352 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2354 /* check if we have more than one portlist relation and we just ignore the disconnect */
2355 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2357 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2358 portlist = ea_endpoint->ep_portlist;
2361 if (portlist->port_id == port_id)
2363 portlist = portlist->next;
2367 PERROR("EPOINT(%d) software error: no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2370 if (message_type != MESSAGE_RELEASE)
2372 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2373 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2374 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2375 message_put(message);
2376 logmessage(message);
2378 ea_endpoint->free_portlist(portlist);
2379 return; /* one relation removed */
2381 if (e_multipoint_cause)
2383 cause = e_multipoint_cause;
2384 location = e_multipoint_location;
2387 cause = param->disconnectinfo.cause;
2388 location = param->disconnectinfo.location;
2391 e_cfnr_call = e_cfnr_release = 0;
2393 /* process hangup */
2394 process_hangup(e_call_cause, e_call_location);
2395 e_multipoint_cause = 0;
2396 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
2398 /* tone to disconnected end */
2399 SPRINT(buffer, "cause_%02x", cause);
2400 if (ea_endpoint->ep_portlist)
2401 set_tone(ea_endpoint->ep_portlist, buffer);
2403 new_state(EPOINT_STATE_IN_DISCONNECT);
2404 if (ea_endpoint->ep_call_id)
2406 int haspatterns = 0;
2407 /* check if pattern is available */
2408 if (ea_endpoint->ep_portlist)
2409 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->earlyb)
2410 #warning wie ist das bei einem asterisk, gibts auch tones?
2411 if (callpbx_countrelations(ea_endpoint->ep_call_id)==2 // we must count relations, in order not to disturb the conference ; NOTE:
2412 && message_type != MESSAGE_RELEASE) // if we release, we are done
2416 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2417 /* indicate patterns */
2418 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2419 message_put(message);
2420 /* connect audio, if not already */
2421 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2422 message->param.channel = CHANNEL_STATE_CONNECT;
2423 message_put(message);
2424 /* send disconnect */
2425 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2426 memcpy(&message->param, param, sizeof(union parameter));
2427 message_put(message);
2428 /* disable encryption if disconnected */
2429 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2431 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2435 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2438 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2439 return; /* must exit here */
2442 /* port MESSAGE_TIMEOUT */
2443 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2447 printlog("%3d incoming TIMEOUT\n",
2448 ea_endpoint->ep_serial
2450 message_type = MESSAGE_DISCONNECT;
2451 switch (param->state)
2453 case PORT_STATE_OUT_SETUP:
2454 case PORT_STATE_OUT_OVERLAP:
2455 /* no user responding */
2456 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2457 return; /* must exit here */
2459 case PORT_STATE_IN_SETUP:
2460 case PORT_STATE_IN_OVERLAP:
2461 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2462 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2465 case PORT_STATE_OUT_PROCEEDING:
2466 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2467 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2468 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2469 return; /* must exit here */
2471 case PORT_STATE_IN_PROCEEDING:
2472 param->disconnectinfo.cause = CAUSE_NOUSER;
2473 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2476 case PORT_STATE_OUT_ALERTING:
2477 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2478 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2479 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2480 return; /* must exit here */
2482 case PORT_STATE_IN_ALERTING:
2483 param->disconnectinfo.cause = CAUSE_NOANSWER;
2484 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2487 case PORT_STATE_IN_DISCONNECT:
2488 case PORT_STATE_OUT_DISCONNECT:
2489 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2490 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2491 return; /* must exit here */
2494 param->disconnectinfo.cause = 31; /* normal unspecified */
2495 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2497 /* release call, disconnect isdn */
2499 new_state(EPOINT_STATE_OUT_DISCONNECT);
2500 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2501 SCPY(e_tone, cause);
2504 set_tone(portlist, cause);
2505 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2506 portlist = portlist->next;
2508 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
2511 /* port MESSAGE_NOTIFY */
2512 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2514 struct message *message;
2518 /* signal to call tool */
2519 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2520 if (param->notifyinfo.notify)
2522 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2525 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2526 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2528 case INFO_NOTIFY_REMOTE_HOLD:
2529 case INFO_NOTIFY_USER_SUSPENDED:
2530 /* tell call about it */
2531 if (ea_endpoint->ep_call_id)
2533 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2534 message->param.channel = CHANNEL_STATE_HOLD;
2535 message_put(message);
2539 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2540 case INFO_NOTIFY_USER_RESUMED:
2541 /* set volume of rx and tx */
2542 if (param->setup.callerinfo.itype == INFO_ITYPE_INTERN)
2543 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2546 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2547 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2548 message->param.mISDNsignal.rxvol = e_ext.txvol;
2549 message->param.mISDNsignal.txvol = e_ext.rxvol;
2550 message_put(message);
2552 /* set current tone */
2554 set_tone(portlist, e_tone);
2555 /* tell call about it */
2556 if (ea_endpoint->ep_call_id)
2558 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2559 message->param.channel = CHANNEL_STATE_CONNECT;
2560 message_put(message);
2565 /* get name of notify */
2566 switch(param->notifyinfo.notify)
2572 logtext = "USER_SUSPENDED";
2575 logtext = "BEARER_SERVICE_CHANGED";
2578 logtext = "USER_RESUMED";
2581 logtext = "CONFERENCE_ESTABLISHED";
2584 logtext = "CONFERENCE_DISCONNECTED";
2587 logtext = "OTHER_PARTY_ADDED";
2590 logtext = "ISOLATED";
2593 logtext = "REATTACHED";
2596 logtext = "OTHER_PARTY_ISOLATED";
2599 logtext = "OTHER_PARTY_REATTACHED";
2602 logtext = "OTHER_PARTY_SPLIT";
2605 logtext = "OTHER_PARTY_DISCONNECTED";
2608 logtext = "CONFERENCE_FLOATING";
2611 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2614 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2617 logtext = "CALL_IS_A_WAITING_CALL";
2620 logtext = "DIVERSION_ACTIVATED";
2623 logtext = "RESERVED_CT_1";
2626 logtext = "RESERVED_CT_2";
2629 logtext = "REVERSE_CHARGING";
2632 logtext = "REMOTE_HOLD";
2635 logtext = "REMOTE_RETRIEVAL";
2638 logtext = "CALL_IS_DIVERTING";
2641 SPRINT(buffer, "indicator=%d", param->notifyinfo.notify - 0x80);
2645 printlog("%3d incoming NOTIFY notify='%s' id='%s'%s\n",
2646 ea_endpoint->ep_serial,
2648 param->notifyinfo.id,
2649 (param->notifyinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":""
2652 /* notify call if available */
2653 if (ea_endpoint->ep_call_id)
2655 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOTIFY);
2656 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2657 message_put(message);
2662 /* port MESSAGE_FACILITY */
2663 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2665 struct message *message;
2667 printlog("%3d incoming FACILITY len='%d'\n",
2668 ea_endpoint->ep_serial,
2669 param->facilityinfo.len
2672 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_FACILITY);
2673 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2674 message_put(message);
2677 /* port MESSAGE_SUSPEND */
2678 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2679 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2681 printlog("%3d incoming SUSPEND\n",
2682 ea_endpoint->ep_serial
2684 /* epoint is now parked */
2685 ea_endpoint->ep_park = 1;
2686 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2687 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2689 /* remove port relation */
2690 ea_endpoint->free_portlist(portlist);
2693 /* port MESSAGE_RESUME */
2694 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2695 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2697 printlog("%3d incoming RESUME\n",
2698 ea_endpoint->ep_serial
2700 /* epoint is now resumed */
2701 ea_endpoint->ep_park = 0;
2706 /* port sends message to the endpoint
2708 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2710 struct port_list *portlist;
2711 struct message *message;
2714 portlist = ea_endpoint->ep_portlist;
2717 if (port_id == portlist->port_id)
2719 portlist = portlist->next;
2723 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);
2727 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_terminal, e_callerinfo.id);
2728 switch(message_type)
2730 case MESSAGE_DATA: /* data from port */
2731 /* send back to source for recording */
2734 message = message_create(ea_endpoint->ep_serial, port_id, EPOINT_TO_PORT, message_type);
2735 memcpy(&message->param, param, sizeof(union parameter));
2736 message_put(message);
2739 /* check if there is a call */
2740 if (!ea_endpoint->ep_call_id)
2742 /* continue if only one portlist */
2743 if (ea_endpoint->ep_portlist->next != NULL)
2745 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2746 memcpy(&message->param, param, sizeof(union parameter));
2747 message_put(message);
2750 case MESSAGE_TONE_EOF: /* tone is end of file */
2751 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2754 if (e_action->index == ACTION_VBOX_PLAY)
2758 if (e_action->index == ACTION_EFI)
2765 case MESSAGE_TONE_COUNTER: /* counter info received */
2766 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);
2768 if (e_action->index == ACTION_VBOX_PLAY)
2770 e_vbox_counter = param->counter.current;
2771 if (param->counter.max >= 0)
2772 e_vbox_counter_max = param->counter.max;
2776 /* PORT sends SETUP message */
2778 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);
2779 if (e_state!=EPOINT_STATE_IDLE)
2781 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2784 port_setup(portlist, message_type, param);
2787 /* PORT sends INFORMATION message */
2788 case MESSAGE_INFORMATION: /* additional digits received */
2789 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call dialing more=%s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->information.number, e_terminal, e_callerinfo.id);
2790 port_information(portlist, message_type, param);
2793 /* PORT sends FACILITY message */
2794 case MESSAGE_FACILITY:
2795 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
2796 port_facility(portlist, message_type, param);
2799 /* PORT sends DTMF message */
2800 case MESSAGE_DTMF: /* dtmf digits received */
2801 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf digit=%c (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->dtmf, e_terminal, e_callerinfo.id);
2802 port_dtmf(portlist, message_type, param);
2805 /* PORT sends CRYPT message */
2806 case MESSAGE_CRYPT: /* crypt response received */
2807 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2808 port_crypt(portlist, message_type, param);
2811 /* PORT sends MORE message */
2812 case MESSAGE_OVERLAP:
2813 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is accepted [overlap dialing] (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
2814 if (e_state != EPOINT_STATE_OUT_SETUP)
2816 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);
2819 port_overlap(portlist, message_type, param);
2822 /* PORT sends PROCEEDING message */
2823 case MESSAGE_PROCEEDING: /* port is proceeding */
2824 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is proceeding (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
2825 if (e_state!=EPOINT_STATE_OUT_SETUP
2826 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2828 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);
2831 port_proceeding(portlist, message_type, param);
2834 /* PORT sends ALERTING message */
2835 case MESSAGE_ALERTING:
2836 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is ringing (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
2837 if (e_state!=EPOINT_STATE_OUT_SETUP
2838 && e_state!=EPOINT_STATE_OUT_OVERLAP
2839 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2841 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);
2844 port_alerting(portlist, message_type, param);
2847 /* PORT sends CONNECT message */
2848 case MESSAGE_CONNECT:
2849 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call connected to %s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_connectinfo.id, e_terminal, e_callerinfo.id);
2850 if (e_state!=EPOINT_STATE_OUT_SETUP
2851 && e_state!=EPOINT_STATE_OUT_OVERLAP
2852 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2853 && e_state!=EPOINT_STATE_OUT_ALERTING)
2855 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2858 port_connect(portlist, message_type, param);
2861 /* PORT sends DISCONNECT message */
2862 case MESSAGE_DISCONNECT: /* port is disconnected */
2863 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_terminal, e_callerinfo.id);
2864 port_disconnect_release(portlist, message_type, param);
2867 /* PORT sends a RELEASE message */
2868 case MESSAGE_RELEASE: /* port releases */
2869 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_terminal, e_callerinfo.id);
2870 /* portlist is release at port_disconnect_release, thanx Paul */
2871 port_disconnect_release(portlist, message_type, param);
2874 /* PORT sends a TIMEOUT message */
2875 case MESSAGE_TIMEOUT:
2876 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received timeout (state=%d).\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, param->state);
2877 port_timeout(portlist, message_type, param);
2878 break; /* release */
2880 /* PORT sends a NOTIFY message */
2881 case MESSAGE_NOTIFY:
2882 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
2883 port_notify(portlist, message_type, param);
2886 /* PORT sends a SUSPEND message */
2887 case MESSAGE_SUSPEND:
2888 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received suspend.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
2889 port_suspend(portlist, message_type, param);
2890 break; /* suspend */
2892 /* PORT sends a RESUME message */
2893 case MESSAGE_RESUME:
2894 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received resume.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
2895 port_resume(portlist, message_type, param);
2899 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: %d\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, message);
2902 /* Note: this endpoint may be destroyed, so we MUST return */
2906 /* messages from port
2908 /* call MESSAGE_CRYPT */
2909 void EndpointAppPBX::call_crypt(struct port_list *portlist, int message_type, union parameter *param)
2911 switch(param->crypt.type)
2913 /* message from remote port to "crypt manager" */
2914 case CU_ACTK_REQ: /* activate key-exchange */
2915 case CU_ACTS_REQ: /* activate shared key */
2916 case CU_DACT_REQ: /* deactivate */
2917 case CU_INFO_REQ: /* request last info message */
2918 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2921 /* message from "crypt manager" to user */
2922 case CU_ACTK_CONF: /* key-echange done */
2923 case CU_ACTS_CONF: /* shared key done */
2924 case CU_DACT_CONF: /* deactivated */
2925 case CU_DACT_IND: /* deactivated */
2926 case CU_ERROR_IND: /* receive error message */
2927 case CU_INFO_IND: /* receive info message */
2928 case CU_INFO_CONF: /* receive info message */
2929 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2933 PERROR("EPOINT(%d) epoint with terminal '%s' (caller id '%s') unknown crypt message: '%d'\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, param->crypt.type);
2937 /* call MESSAGE_INFORMATION */
2938 void EndpointAppPBX::call_information(struct port_list *portlist, int message_type, union parameter *param)
2940 struct message *message;
2946 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2947 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2948 message_put(message);
2949 logmessage(message);
2950 portlist = portlist->next;
2954 /* call MESSAGE_FACILITY */
2955 void EndpointAppPBX::call_facility(struct port_list *portlist, int message_type, union parameter *param)
2957 struct message *message;
2959 if (!e_ext.facility)
2966 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2967 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2968 message_put(message);
2969 logmessage(message);
2970 portlist = portlist->next;
2974 /* call MESSAGE_MORE */
2975 void EndpointAppPBX::call_overlap(struct port_list *portlist, int message_type, union parameter *param)
2977 struct message *message;
2979 new_state(EPOINT_STATE_IN_OVERLAP);
2982 if (e_call_pattern && e_ext.own_setup)
2984 /* disconnect audio */
2985 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2986 message->param.channel = CHANNEL_STATE_HOLD;
2987 message_put(message);
2989 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2991 set_tone(portlist, "dialtone");
2995 set_tone(portlist, "dialpbx");
2997 set_tone(portlist, "dialtone");
3000 /* call MESSAGE_PROCEEDING */
3001 void EndpointAppPBX::call_proceeding(struct port_list *portlist, int message_type, union parameter *param)
3003 struct message *message;
3005 new_state(EPOINT_STATE_IN_PROCEEDING);
3007 /* own proceeding tone */
3010 /* connect / disconnect audio */
3011 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3012 if (e_ext.own_proceeding)
3013 message->param.channel = CHANNEL_STATE_HOLD;
3015 message->param.channel = CHANNEL_STATE_CONNECT;
3016 message_put(message);
3018 // UCPY(e_call_tone, "proceeding");
3021 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3022 message_put(message);
3023 logmessage(message);
3025 set_tone(portlist, "proceeding");
3028 /* call MESSAGE_ALERTING */
3029 void EndpointAppPBX::call_alerting(struct port_list *portlist, int message_type, union parameter *param)
3031 struct message *message;
3033 new_state(EPOINT_STATE_IN_ALERTING);
3035 /* own alerting tone */
3038 /* connect / disconnect audio */
3039 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3040 if (e_ext.own_alerting)
3041 message->param.channel = CHANNEL_STATE_HOLD;
3043 message->param.channel = CHANNEL_STATE_CONNECT;
3044 message_put(message);
3048 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
3049 message_put(message);
3050 logmessage(message);
3052 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3054 set_tone(portlist, "ringing");
3058 set_tone(portlist, "ringpbx");
3060 set_tone(portlist, "ringing");
3063 /* call MESSAGE_CONNECT */
3064 void EndpointAppPBX::call_connect(struct port_list *portlist, int message_type, union parameter *param)
3066 struct message *message;
3068 new_state(EPOINT_STATE_CONNECT);
3069 // UCPY(e_call_tone, "");
3071 e_dtmf = 1; /* allow dtmf */
3073 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
3076 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3077 memcpy(&message->param, param, sizeof(union parameter));
3078 /* screen by interface */
3079 if (e_connectinfo.interface[0])
3081 /* screen incoming caller id */
3082 screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present);
3084 memcpy(&message->param.connnectinfo, e_connectinfo);
3086 /* screen clip if prefix is required */
3087 if (e_terminal[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3089 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3090 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
3091 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3094 /* use internal caller id */
3095 if (e_terminal[0] && e_connectinfo.intern[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3097 SCPY(message->param.connectinfo.id, e_connectinfo.intern);
3098 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3101 /* handle restricted caller ids */
3102 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);
3103 /* display callerid if desired for extension */
3104 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));
3106 /* use conp, if enabld */
3108 message->param.connectinfo.name[0] = '\0';
3111 message_put(message);
3112 logmessage(message);
3114 set_tone(portlist, NULL);
3116 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3117 message->param.channel = CHANNEL_STATE_CONNECT;
3118 message_put(message);
3122 /* call MESSAGE_DISCONNECT MESSAGE_RELEASE */
3123 void EndpointAppPBX::call_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
3126 struct message *message;
3129 /* be sure that we are active */
3131 e_tx_state = NOTIFY_STATE_ACTIVE;
3133 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3134 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3136 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
3138 /* set time for power dialing */
3139 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3142 /* set redial tone */
3143 if (ea_endpoint->ep_portlist)
3147 set_tone(ea_endpoint->ep_portlist, "redial");
3148 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') redialing in %d seconds\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, (int)e_powerdelay);
3149 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3150 if (e_state==EPOINT_STATE_IN_OVERLAP)
3152 new_state(EPOINT_STATE_IN_PROCEEDING);
3155 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3156 message_put(message);
3157 logmessage(message);
3159 /* caused the error, that the first knock sound was not there */
3160 /* set_tone(portlist, "proceeding"); */
3162 /* send display of powerdialing */
3163 if (e_ext.display_dialing)
3167 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3169 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3171 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3172 message_put(message);
3173 logmessage(message);
3174 portlist = portlist->next;
3183 if ((e_state!=EPOINT_STATE_CONNECT
3184 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3185 && e_state!=EPOINT_STATE_IN_OVERLAP
3186 && e_state!=EPOINT_STATE_IN_PROCEEDING
3187 && e_state!=EPOINT_STATE_IN_ALERTING)
3188 || !ea_endpoint->ep_portlist) /* or no port */
3190 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3191 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, call, port */
3192 return; /* must exit here */
3197 e_call_cause = param->disconnectinfo.cause;
3198 e_call_location = param->disconnectinfo.location;
3201 /* on release we need the audio again! */
3202 if (message_type == MESSAGE_RELEASE)
3205 ea_endpoint->ep_call_id = 0;
3207 /* disconnect and select tone */
3208 new_state(EPOINT_STATE_OUT_DISCONNECT);
3209 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3210 /* if own_cause, we must release the call */
3211 if (e_ext.own_cause /* own cause */
3212 || !e_call_pattern) /* no patterns */
3214 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);
3215 if (message_type != MESSAGE_RELEASE)
3216 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
3218 } else /* else we enable audio */
3220 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3221 message->param.channel = CHANNEL_STATE_CONNECT;
3222 message_put(message);
3224 /* send disconnect message */
3225 SCPY(e_tone, cause);
3228 set_tone(portlist, cause);
3229 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3230 portlist = portlist->next;
3234 /* call MESSAGE_SETUP */
3235 void EndpointAppPBX::call_setup(struct port_list *portlist, int message_type, union parameter *param)
3237 struct message *message;
3239 /* if we already in setup state, we just update the dialing with new digits */
3240 if (e_state == EPOINT_STATE_OUT_SETUP
3241 || e_state == EPOINT_STATE_OUT_OVERLAP)
3243 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3244 /* if digits changed, what we have already dialed */
3245 if (!!strncmp(e_dialinginfo.number,param->setup.dialinginfo.number,strlen(e_dialinginfo.number)))
3247 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);
3248 /* release all ports */
3249 while((portlist = ea_endpoint->ep_portlist))
3251 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3252 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3253 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3254 message_put(message);
3255 logmessage(message);
3256 ea_endpoint->free_portlist(portlist);
3259 /* disconnect audio */
3260 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3261 message->param.channel = CHANNEL_STATE_HOLD;
3262 message_put(message);
3264 /* get dialing info */
3265 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3266 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3267 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3268 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3269 new_state(EPOINT_STATE_OUT_OVERLAP);
3272 e_redial = now_d + 1; /* set redial one second in the future */
3275 /* if we have a pending redial, so we just adjust the dialing number */
3278 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);
3279 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3282 if (!ea_endpoint->ep_portlist)
3284 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3286 if (ea_endpoint->ep_portlist->next)
3288 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3290 if (e_state == EPOINT_STATE_OUT_SETUP)
3293 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);
3294 SCAT(e_dialing_queue, param->setup.dialinginfo.number + strlen(e_dialinginfo.number));
3298 /* get what we have not dialed yet */
3299 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));
3300 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3301 SCPY(message->param.information.number, param->setup.dialinginfo.number + strlen(e_dialinginfo.number));
3302 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3303 message_put(message);
3304 logmessage(message);
3306 /* always store what we have dialed or queued */
3307 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3311 if (e_state != EPOINT_STATE_IDLE)
3313 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3316 /* if an internal extension is dialed, copy that number */
3317 if (param->setup.dialinginfo.itype==INFO_ITYPE_INTERN || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3318 SCPY(e_terminal, param->setup.dialinginfo.number);
3319 /* if an internal extension is dialed, get extension's info about caller */
3322 if (!read_extension(&e_ext, e_terminal))
3324 e_terminal[0] = '\0';
3325 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_terminal);
3329 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3330 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3331 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3332 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3334 /* screen by interface */
3335 if (e_callerinfo.interface[0])
3337 /* screen incoming caller id */
3338 screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present);
3341 /* process (voice over) data calls */
3342 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3344 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_terminal);
3345 memset(&e_capainfo, 0, sizeof(e_capainfo));
3346 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3347 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3348 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3351 new_state(EPOINT_STATE_OUT_SETUP);
3352 /* call special setup routine */
3356 /* call MESSAGE_mISDNSIGNAL */
3357 void EndpointAppPBX::call_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3359 struct message *message;
3363 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3364 memcpy(&message->param, param, sizeof(union parameter));
3365 message_put(message);
3366 portlist = portlist->next;
3370 /* call MESSAGE_NOTIFY */
3371 void EndpointAppPBX::call_notify(struct port_list *portlist, int message_type, union parameter *param)
3373 struct message *message;
3376 if (param->notifyinfo.notify)
3378 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3379 // /* if notification was generated locally, we turn hold music on/off */
3380 // if (param->notifyinfo.local)
3381 // 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)
3386 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3390 set_tone(portlist, "");
3391 portlist = portlist->next;
3393 portlist = ea_endpoint->ep_portlist;
3398 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3402 set_tone(portlist, "hold");
3403 portlist = portlist->next;
3405 portlist = ea_endpoint->ep_portlist;
3410 /* save new state */
3411 e_tx_state = new_state;
3414 /* notify port(s) about it */
3417 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3418 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3419 /* handle restricted caller ids */
3420 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);
3421 /* display callerid if desired for extension */
3422 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));
3423 message_put(message);
3424 logmessage(message);
3425 portlist = portlist->next;
3429 /* call sends messages to the endpoint
3431 void EndpointAppPBX::ea_message_call(unsigned long call_id, int message_type, union parameter *param)
3433 struct port_list *portlist;
3434 struct message *message;
3438 PERROR("EPOINT(%d) error: call == NULL.\n", ea_endpoint->ep_serial);
3442 portlist = ea_endpoint->ep_portlist;
3444 /* send MESSAGE_DATA to port */
3445 if (call_id == ea_endpoint->ep_call_id)
3447 if (message_type == MESSAGE_DATA)
3449 /* skip if no port relation */
3452 /* skip if more than one port relation */
3455 /* send audio data to port */
3456 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DATA);
3457 memcpy(&message->param, param, sizeof(union parameter));
3458 message_put(message);
3463 // 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_terminal, e_callerinfo.id, e_state);
3464 switch(message_type)
3466 /* CALL SENDS CRYPT message */
3468 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received crypt message: '%d'\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, param->crypt.type);
3469 call_crypt(portlist, message_type, param);
3472 /* CALL sends INFORMATION message */
3473 case MESSAGE_INFORMATION:
3474 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received more digits: '%s'\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, param->information.number);
3475 call_information(portlist, message_type, param);
3478 /* CALL sends FACILITY message */
3479 case MESSAGE_FACILITY:
3480 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received facility\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3481 call_facility(portlist, message_type, param);
3484 /* CALL sends OVERLAP message */
3485 case MESSAGE_OVERLAP:
3486 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received 'more info available'\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3487 if (e_state!=EPOINT_STATE_IN_SETUP
3488 && e_state!=EPOINT_STATE_IN_OVERLAP)
3490 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3493 call_overlap(portlist, message_type, param);
3496 /* CALL sends PROCEEDING message */
3497 case MESSAGE_PROCEEDING:
3498 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s (caller id '%s') received proceeding\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3499 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3501 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3504 call_proceeding(portlist, message_type, param);
3507 /* CALL sends ALERTING message */
3508 case MESSAGE_ALERTING:
3509 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received alerting\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3510 if (e_state!=EPOINT_STATE_IN_OVERLAP
3511 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3513 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3516 call_alerting(portlist, message_type, param);
3519 /* CALL sends CONNECT message */
3520 case MESSAGE_CONNECT:
3521 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received connect\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3522 if (e_state!=EPOINT_STATE_IN_OVERLAP
3523 && e_state!=EPOINT_STATE_IN_PROCEEDING
3524 && e_state!=EPOINT_STATE_IN_ALERTING)
3526 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3529 call_connect(portlist, message_type, param);
3532 /* CALL sends DISCONNECT/RELEASE message */
3533 case MESSAGE_DISCONNECT: /* call disconnect */
3534 case MESSAGE_RELEASE: /* call releases */
3535 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_terminal, e_callerinfo.id, (message_type==MESSAGE_DISCONNECT)?"disconnect":"release", param->disconnectinfo.cause, param->disconnectinfo.location);
3536 call_disconnect_release(portlist, message_type, param);
3539 /* CALL sends SETUP message */
3541 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);
3542 call_setup(portlist, message_type, param);
3546 /* CALL sends special mISDNSIGNAL message */
3547 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3548 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received mISDNsignal message.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3549 call_mISDNsignal(portlist, message_type, param);
3552 /* CALL has pattern available */
3553 case MESSAGE_PATTERN: /* indicating pattern available */
3554 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern availability.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3555 if (!e_call_pattern)
3557 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3562 set_tone(portlist, NULL);
3563 portlist = portlist->next;
3565 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3566 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3567 message->param.channel = CHANNEL_STATE_CONNECT;
3568 message_put(message);
3569 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3570 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_REMOTE_AUDIO);
3571 // message->param.channel = CHANNEL_STATE_CONNECT;
3572 // message_put(message);
3573 // patterns are available, remote already connected audio
3577 /* CALL has no pattern available */
3578 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3579 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern NOT available.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3582 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3584 /* disconnect our audio tx and rx */
3585 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3586 message->param.channel = CHANNEL_STATE_HOLD;
3587 message_put(message);
3592 /* CALL (dunno at the moment) */
3593 case MESSAGE_REMOTE_AUDIO:
3594 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received audio remote request.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3595 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3596 message->param.channel = param->channel;
3597 message_put(message);
3601 /* CALL sends a notify message */
3602 case MESSAGE_NOTIFY:
3603 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3604 call_notify(portlist, message_type, param);
3608 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: #%d\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, message);
3613 /* pick_call will connect the first incoming call found. the endpoint
3614 * will receivce a MESSAGE_CONNECT.
3616 int match_list(char *list, char *item)
3618 char *end, *next = NULL;
3620 /* no list make matching */
3626 /* eliminate white spaces */
3627 while (*list <= ' ')
3634 /* if end of list is reached, we return */
3635 if (list[0] == '\0')
3637 /* if we have more than one entry (left) */
3638 if ((end = strchr(list, ',')))
3641 next = end = strchr(list, '\0');
3642 while (*(end-1) <= ' ')
3644 /* if string part matches item */
3645 if (!strncmp(list, item, end-list))
3651 void EndpointAppPBX::pick_call(char *extensions)
3653 struct message *message;
3654 struct port_list *portlist;
3656 class EndpointAppPBX *eapp, *found;
3658 class CallPBX *callpbx;
3659 struct call_relation *relation;
3662 /* find an endpoint that is ringing internally or vbox with higher priority */
3665 eapp = apppbx_first;
3668 if (eapp!=this && ea_endpoint->ep_portlist)
3670 portlist = eapp->ea_endpoint->ep_portlist;
3673 if ((port = find_port_id(portlist->port_id)))
3675 if (port->p_type == PORT_TYPE_VBOX_OUT)
3677 if (match_list(extensions, eapp->e_terminal))
3684 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3685 && port->p_state==PORT_STATE_OUT_ALERTING)
3686 if (match_list(extensions, eapp->e_terminal))
3691 portlist = portlist->next;
3699 /* if no endpoint found */
3702 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);
3704 set_tone(ea_endpoint->ep_portlist, "cause_10");
3705 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3706 new_state(EPOINT_STATE_OUT_DISCONNECT);
3711 if (ea_endpoint->ep_call_id)
3713 PERROR("EPOINT(%d) we already have a call. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3716 if (!eapp->ea_endpoint->ep_call_id)
3718 PERROR("EPOINT(%d) ringing endpoint has no call.\n", ea_endpoint->ep_serial);
3721 call = find_call_id(eapp->ea_endpoint->ep_call_id);
3724 PERROR("EPOINT(%d) ringing endpoint's call not found.\n", ea_endpoint->ep_serial);
3727 if (callpbx->c_type != CALL_TYPE_PBX)
3729 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's call is not a PBX call, so we must reject.\n", ea_endpoint->ep_serial);
3732 callpbx = (class CallPBX *)call;
3733 relation = callpbx->c_relation;
3736 PERROR("EPOINT(%d) ringing endpoint's call has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3739 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3741 relation = relation->next;
3744 PERROR("EPOINT(%d) ringing endpoint's call has no relation to that call. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3749 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3751 if (options.deb & DEBUG_EPOINT)
3753 class Call *debug_c = call_first;
3754 class Endpoint *debug_e = epoint_first;
3755 class Port *debug_p = port_first;
3757 callpbx_debug(callpbx, "EndpointAppPBX::pick_call(before)");
3759 PDEBUG(DEBUG_EPOINT, "showing all calls:\n");
3762 PDEBUG(DEBUG_EPOINT, "call=%ld\n", debug_c->c_serial);
3763 debug_c = debug_c->next;
3765 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3768 PDEBUG(DEBUG_EPOINT, "ep=%ld, call=%ld\n", debug_e->ep_serial, debug_e->ep_call_id);
3769 debug_e = debug_e->next;
3771 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3774 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3775 debug_p = debug_p->next;
3780 ea_endpoint->ep_call_id = eapp->ea_endpoint->ep_call_id; /* we get the call */
3781 relation->epoint_id = ea_endpoint->ep_serial; /* the call gets us */
3782 eapp->ea_endpoint->ep_call_id = 0; /* the ringing endpoint will get disconnected */
3784 /* connnecting our endpoint */
3785 new_state(EPOINT_STATE_CONNECT);
3787 set_tone(ea_endpoint->ep_portlist, NULL);
3789 /* now we send a release to the ringing endpoint */
3790 message = message_create(ea_endpoint->ep_call_id, eapp->ea_endpoint->ep_serial, CALL_TO_EPOINT, MESSAGE_RELEASE);
3791 message->param.disconnectinfo.cause = 26; /* non selected user clearing */
3792 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3793 message_put(message);
3795 /* we send a connect to the call with our caller id */
3796 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CONNECT);
3797 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3798 message->param.connectinfo.present = e_callerinfo.present;
3799 message->param.connectinfo.screen = e_callerinfo.screen;
3800 message->param.connectinfo.itype = e_callerinfo.itype;
3801 message->param.connectinfo.ntype = e_callerinfo.ntype;
3802 message_put(message);
3804 /* we send a connect to our port with the remote callerid */
3805 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3806 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3807 message->param.connectinfo.present = eapp->e_callerinfo.present;
3808 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3809 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3810 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3811 /* handle restricted caller ids */
3812 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);
3813 /* display callerid if desired for extension */
3814 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));
3815 message_put(message);
3817 /* we send a connect to the audio path (not for vbox) */
3818 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3819 message->param.channel = CHANNEL_STATE_CONNECT;
3820 message_put(message);
3822 /* beeing paranoid, we make call update */
3823 callpbx->c_mixer = 1;
3825 if (options.deb & DEBUG_EPOINT)
3827 class Call *debug_c = call_first;
3828 class Endpoint *debug_e = epoint_first;
3829 class Port *debug_p = port_first;
3831 callpbx_debug(callpbx, "EndpointAppPBX::pick_call(after)");
3833 PDEBUG(DEBUG_EPOINT, "showing all calls:\n");
3836 PDEBUG(DEBUG_EPOINT, "call=%ld\n", debug_c->c_serial);
3837 debug_c = debug_c->next;
3839 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3842 PDEBUG(DEBUG_EPOINT, "ep=%ld, call=%ld\n", debug_e->ep_serial, debug_e->ep_call_id);
3843 debug_e = debug_e->next;
3845 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3848 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3849 debug_p = debug_p->next;
3855 /* join calls (look for a call that is on hold (same isdn interface/terminal))
3857 void EndpointAppPBX::join_call(void)
3859 struct message *message;
3860 struct call_relation *our_relation, *other_relation;
3861 struct call_relation **our_relation_pointer, **other_relation_pointer;
3862 class Call *our_call, *other_call;
3863 class CallPBX *our_callpbx, *other_callpbx;
3864 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3865 class Port *our_port, *other_port;
3866 class Pdss1 *our_pdss1, *other_pdss1;
3868 /* are we a candidate to join a call */
3869 our_call = find_call_id(ea_endpoint->ep_call_id);
3872 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our call doesn't exist anymore.\n", ea_endpoint->ep_serial);
3875 if (our_call->c_type != CALL_TYPE_PBX)
3877 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: call is not a pbx call.\n", ea_endpoint->ep_serial);
3880 our_callpbx = (class CallPBX *)our_call;
3881 if (!ea_endpoint->ep_portlist)
3883 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3888 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3891 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3894 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3897 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3899 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3902 our_pdss1 = (class Pdss1 *)our_port;
3904 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3905 other_eapp = apppbx_first;
3908 if (other_eapp == this)
3910 other_eapp = other_eapp->next;
3913 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_terminal, (other_eapp->ea_endpoint->ep_portlist)?"YES":"NO", other_eapp->ea_endpoint->ep_call_id);
3914 if (other_eapp->e_terminal[0] /* has terminal */
3915 && other_eapp->ea_endpoint->ep_portlist /* has port */
3916 && other_eapp->ea_endpoint->ep_call_id) /* has call */
3918 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3919 if (other_port) /* port still exists */
3921 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3922 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3924 other_pdss1 = (class Pdss1 *)other_port;
3925 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);
3926 if (other_pdss1->p_m_hold /* port is on hold */
3927 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3928 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3932 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3936 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3939 other_eapp = other_eapp->next;
3943 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3946 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3948 /* if we have the same call */
3949 if (other_eapp->ea_endpoint->ep_call_id == ea_endpoint->ep_call_id)
3951 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same call.\n", ea_endpoint->ep_serial);
3954 other_call = find_call_id(other_eapp->ea_endpoint->ep_call_id);
3957 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other call doesn't exist anymore.\n", ea_endpoint->ep_serial);
3960 if (other_call->c_type != CALL_TYPE_PBX)
3962 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other call is not a pbx call.\n", ea_endpoint->ep_serial);
3965 other_callpbx = (class CallPBX *)other_call;
3966 if (our_callpbx->c_partyline && other_callpbx->c_partyline)
3968 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both calls are partylines.\n", ea_endpoint->ep_serial);
3972 /* remove relation to endpoint for call on hold */
3973 other_relation = other_callpbx->c_relation;
3974 other_relation_pointer = &other_callpbx->c_relation;
3975 while(other_relation)
3977 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
3979 /* detach other endpoint on hold */
3980 *other_relation_pointer = other_relation->next;
3981 memset(other_relation, 0, sizeof(struct call_relation));
3982 free(other_relation);
3984 other_relation = *other_relation_pointer;
3985 other_eapp->ea_endpoint->ep_call_id = NULL;
3989 /* change call/hold pointer of endpoint to the new call */
3990 temp_epoint = find_epoint_id(other_relation->epoint_id);
3993 if (temp_epoint->ep_call_id == other_call->c_serial)
3994 temp_epoint->ep_call_id = our_call->c_serial;
3997 other_relation_pointer = &other_relation->next;
3998 other_relation = other_relation->next;
4000 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on call relinked (to our call).\n", ea_endpoint->ep_serial);
4002 /* join call relations */
4003 our_relation = our_callpbx->c_relation;
4004 our_relation_pointer = &our_callpbx->c_relation;
4007 our_relation_pointer = &our_relation->next;
4008 our_relation = our_relation->next;
4010 *our_relation_pointer = other_callpbx->c_relation;
4011 other_callpbx->c_relation = NULL;
4012 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
4014 /* release endpoint on hold */
4015 message = message_create(other_callpbx->c_serial, other_eapp->ea_endpoint->ep_serial, CALL_TO_EPOINT, MESSAGE_RELEASE);
4016 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
4017 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
4018 message_put(message);
4020 /* if we are not a partyline, we get partyline state from other call */
4021 our_callpbx->c_partyline += other_callpbx->c_partyline;
4023 /* remove empty call */
4025 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-call completely removed!\n");
4027 /* mixer must update */
4028 our_callpbx->c_mixer = 1; /* update mixer flag */
4030 /* we send a retrieve to that endpoint */
4031 // mixer will update the hold-state of the call and send it to the endpoints is changes
4035 /* check if we have an external call
4036 * this is used to check for encryption ability
4038 int EndpointAppPBX::check_external(char **errstr, class Port **port)
4040 struct call_relation *relation;
4042 class CallPBX *callpbx;
4043 class Endpoint *epoint;
4045 /* some paranoia check */
4046 if (!ea_endpoint->ep_portlist)
4048 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4049 *errstr = "No Call";
4054 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4055 *errstr = "No Call";
4059 /* check if we have a call with 2 parties */
4060 call = find_call_id(ea_endpoint->ep_call_id);
4063 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no call.\n", ea_endpoint->ep_serial);
4064 *errstr = "No Call";
4067 if (call->c_type != CALL_TYPE_PBX)
4069 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call is nto a pbx call.\n", ea_endpoint->ep_serial);
4070 *errstr = "No PBX Call";
4073 callpbx = (class CallPBX *)call;
4074 relation = callpbx->c_relation;
4077 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no relation.\n", ea_endpoint->ep_serial);
4078 *errstr = "No Call";
4081 if (!relation->next)
4083 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no 2nd relation.\n", ea_endpoint->ep_serial);
4084 *errstr = "No Call";
4087 if (relation->next->next)
4089 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has more than two relations.\n", ea_endpoint->ep_serial);
4090 *errstr = "Err: Conference";
4093 if (relation->epoint_id == ea_endpoint->ep_serial)
4095 relation = relation->next;
4096 if (relation->epoint_id == ea_endpoint->ep_serial)
4098 PERROR("EPOINT(%d) SOFTWARE ERROR: both call relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4099 *errstr = "Software Error";
4104 /* check remote port for external call */
4105 epoint = find_epoint_id(relation->epoint_id);
4108 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4109 *errstr = "No Call";
4112 if (!epoint->ep_portlist)
4114 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4115 *errstr = "No Call";
4118 *port = find_port_id(epoint->ep_portlist->port_id);
4121 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4122 *errstr = "No Call";
4125 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4127 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4128 *errstr = "No Ext Call";
4131 if ((*port)->p_state != PORT_STATE_CONNECT)
4133 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4134 *errstr = "No Ext Connect";
4140 void EndpointAppPBX::logmessage(struct message *message)
4144 char *logtext = "unknown";
4147 if (message->flow != EPOINT_TO_PORT)
4149 PERROR("EPOINT(%d) message not of correct flow type-\n", ea_endpoint->ep_serial);
4153 switch(message->type)
4156 port = find_port_id(message->id_to);
4159 if (port->p_type == PORT_TYPE_DSS1_NT_OUT)
4161 pdss1 = (class Pdss1 *)port;
4162 printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to intern='%s' port='%d' (NT)\n",
4163 ea_endpoint->ep_serial,
4164 (message->param.setup.callerinfo.intern[0])?"intern":"extern",
4165 (message->param.setup.callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
4166 (message->param.setup.callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
4167 (message->param.setup.redirinfo.id[0])?"redirected='":"",
4168 message->param.setup.redirinfo.id,
4169 (message->param.setup.redirinfo.id[0])?"'":"",
4170 message->param.setup.dialinginfo.number,
4171 pdss1->p_m_mISDNport->portnum
4174 if (port->p_type == PORT_TYPE_DSS1_TE_OUT)
4176 pdss1 = (class Pdss1 *)port;
4177 printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to extern='%s' port='%d' (TE)\n",
4178 ea_endpoint->ep_serial,
4179 (message->param.setup.callerinfo.intern[0])?"intern":"extern",
4180 (message->param.setup.callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
4181 (message->param.setup.callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
4182 (message->param.setup.redirinfo.id[0])?"redirected='":"",
4183 message->param.setup.redirinfo.id,
4184 (message->param.setup.redirinfo.id[0])?"'":"",
4185 message->param.setup.dialinginfo.number,
4186 pdss1->p_m_mISDNport->portnum
4189 if (port->p_type == PORT_TYPE_VBOX_OUT)
4191 printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to vbox='%s'\n",
4192 ea_endpoint->ep_serial,
4193 (message->param.setup.callerinfo.intern[0])?"intern":"extern",
4194 (message->param.setup.callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
4195 (message->param.setup.callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
4196 (message->param.setup.redirinfo.id[0])?"redirected='":"",
4197 message->param.setup.redirinfo.id,
4198 (message->param.setup.redirinfo.id[0])?"'":"",
4199 message->param.setup.dialinginfo.number
4204 case MESSAGE_OVERLAP:
4205 printlog("%3d outgoing SETUP ACKNOWLEDGE\n",
4206 ea_endpoint->ep_serial
4210 case MESSAGE_PROCEEDING:
4211 printlog("%3d outgoing PROCEEDING\n",
4212 ea_endpoint->ep_serial
4216 case MESSAGE_ALERTING:
4217 printlog("%3d outgoing ALERTING\n",
4218 ea_endpoint->ep_serial
4222 case MESSAGE_CONNECT:
4223 printlog("%3d outgoing CONNECT id='%s'%s\n",
4224 ea_endpoint->ep_serial,
4225 message->param.connectinfo.id,
4226 (message->param.connectinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":""
4230 case MESSAGE_DISCONNECT:
4231 printlog("%3d outgoing DISCONNECT cause='%d' (%s) location='%d' (%s) display='%s'\n",
4232 ea_endpoint->ep_serial,
4233 message->param.disconnectinfo.cause,
4234 (message->param.disconnectinfo.cause>0 && message->param.disconnectinfo.cause<128)?isdn_cause[message->param.disconnectinfo.cause].english:"-",
4235 message->param.disconnectinfo.location,
4236 (message->param.disconnectinfo.location>=0 && message->param.disconnectinfo.location<16)?isdn_location[message->param.disconnectinfo.location].english:"-",
4237 message->param.disconnectinfo.display
4241 case MESSAGE_RELEASE:
4242 printlog("%3d outgoing RELEASE cause='%d' (%s) location='%d' (%s)\n",
4243 ea_endpoint->ep_serial,
4244 message->param.disconnectinfo.cause,
4245 (message->param.disconnectinfo.cause>0 && message->param.disconnectinfo.cause<128)?isdn_cause[message->param.disconnectinfo.cause].english:"-",
4246 message->param.disconnectinfo.location,
4247 (message->param.disconnectinfo.location>=0 && message->param.disconnectinfo.location<16)?isdn_location[message->param.disconnectinfo.location].english:"-"
4251 case MESSAGE_NOTIFY:
4252 switch(message->param.notifyinfo.notify)
4258 logtext = "USER_SUSPENDED";
4261 logtext = "BEARER_SERVICE_CHANGED";
4264 logtext = "USER_RESUMED";
4267 logtext = "CONFERENCE_ESTABLISHED";
4270 logtext = "CONFERENCE_DISCONNECTED";
4273 logtext = "OTHER_PARTY_ADDED";
4276 logtext = "ISOLATED";
4279 logtext = "REATTACHED";
4282 logtext = "OTHER_PARTY_ISOLATED";
4285 logtext = "OTHER_PARTY_REATTACHED";
4288 logtext = "OTHER_PARTY_SPLIT";
4291 logtext = "OTHER_PARTY_DISCONNECTED";
4294 logtext = "CONFERENCE_FLOATING";
4297 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4300 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4303 logtext = "CALL_IS_A_WAITING_CALL";
4306 logtext = "DIVERSION_ACTIVATED";
4309 logtext = "RESERVED_CT_1";
4312 logtext = "RESERVED_CT_2";
4315 logtext = "REVERSE_CHARGING";
4318 logtext = "REMOTE_HOLD";
4321 logtext = "REMOTE_RETRIEVAL";
4324 logtext = "CALL_IS_DIVERTING";
4327 SPRINT(buffer, "indicator=%d", message->param.notifyinfo.notify - 0x80);
4331 printlog("%3d outgoing NOTIFY notify='%s' id='%s'%s display='%s'\n",
4332 ea_endpoint->ep_serial,
4334 message->param.notifyinfo.id,
4335 (message->param.notifyinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
4336 message->param.notifyinfo.display
4340 case MESSAGE_INFORMATION:
4341 printlog("%3d outgoing INFORMATION information='%s'\n",
4342 ea_endpoint->ep_serial,
4343 message->param.information.number
4347 case MESSAGE_FACILITY:
4348 printlog("%3d outgoing FACILITY len='%d'\n",
4349 ea_endpoint->ep_serial,
4350 message->param.facilityinfo.len
4355 printlog("%3d outgoing TONE dir='%s' name='%s'\n",
4356 ea_endpoint->ep_serial,
4357 message->param.tone.dir,
4358 message->param.tone.name
4363 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message->type);
4367 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4369 struct message *message;
4373 if (!portlist->port_id)
4376 if (!e_connectedmode)
4378 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4379 message->param.disconnectinfo.cause = cause;
4380 message->param.disconnectinfo.location = location;
4382 SCPY(message->param.disconnectinfo.display, display);
4384 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4387 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4389 SCPY(message->param.notifyinfo.display, display);
4391 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4393 message_put(message);
4394 logmessage(message);