1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 #include <sys/types.h>
24 class EndpointAppPBX *apppbx_first = NULL;
27 * EndpointAppPBX constructor
29 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint) : EndpointApp(epoint)
31 class EndpointAppPBX **apppointer;
33 /* add application to chain */
35 apppointer = &apppbx_first;
37 apppointer = &((*apppointer)->next);
41 memset(&e_ext, 0, sizeof(struct extension));
42 e_ext.rights = 4; /* international */
43 e_ext.rxvol = e_ext.txvol = 256;
44 e_state = EPOINT_STATE_IDLE;
45 e_ext.number[0] = '\0';
46 e_extension_interface[0] = '\0';
47 memset(&e_callerinfo, 0, sizeof(struct caller_info));
48 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
49 memset(&e_connectinfo, 0, sizeof(struct connect_info));
50 memset(&e_redirinfo, 0, sizeof(struct redir_info));
51 memset(&e_capainfo, 0, sizeof(struct capa_info));
54 e_ruleset = ruleset_main;
56 e_rule = e_ruleset->rule_first;
61 e_match_to_action = NULL;
63 e_extdialing = e_dialinginfo.id;
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;
129 FATAL("Endpoint not in endpoint's list.\n");
136 * trace header for application
138 void EndpointAppPBX::trace_header(char *name, int direction)
142 char msgtext[sizeof(_trace.name)];
146 /* init trace with given values */
149 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype),
153 ea_endpoint->ep_serial,
160 /* set new endpoint state
162 void EndpointAppPBX::new_state(int state)
165 if (e_state != state)
167 trace_header("NEW STATE", DIRECTION_NONE);
168 add_trace("state", "old", "%s", state_name[e_state]);
169 add_trace("state", "new", "%s", state_name[state]);
178 * out==0: incomming caller id, out==1: outgoing caller id
180 void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
183 struct interface_msn *ifmsn;
184 struct interface_screen *ifscreen;
187 /* screen incoming caller id */
190 /* check for MSN numbers, use first MSN if no match */
192 ifmsn = interface->ifmsn;
197 if (!strcmp(ifmsn->msn, id))
205 trace_header("SCREEN (found in list)", DIRECTION_IN);
206 add_trace("msn", NULL, "%s", id);
209 if (!ifmsn && msn1) // not in list, first msn given
211 trace_header("SCREEN (not found in list)", DIRECTION_IN);
212 add_trace("msn", "given", "%s", id);
213 add_trace("msn", "used", "%s", msn1);
215 UNCPY(id, msn1, idsize);
220 /* check screen list */
222 ifscreen = interface->ifscreen_out;
224 ifscreen = interface->ifscreen_in;
227 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
228 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
230 if (strchr(ifscreen->match,'%'))
232 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
236 if (!strcmp(ifscreen->match, id))
240 ifscreen = ifscreen->next;
242 if (ifscreen) // match
244 trace_header("SCREEN (found in list)", out?DIRECTION_OUT:DIRECTION_IN);
247 case INFO_NTYPE_UNKNOWN:
248 add_trace("given", "type", "unknown");
250 case INFO_NTYPE_SUBSCRIBER:
251 add_trace("given", "type", "subscriber");
253 case INFO_NTYPE_NATIONAL:
254 add_trace("given", "type", "national");
256 case INFO_NTYPE_INTERNATIONAL:
257 add_trace("given", "type", "international");
262 case INFO_PRESENT_ALLOWED:
263 add_trace("given", "present", "allowed");
265 case INFO_PRESENT_RESTRICTED:
266 add_trace("given", "present", "restricted");
268 case INFO_PRESENT_NOTAVAIL:
269 add_trace("given", "present", "not available");
272 add_trace("given", "id", "%s", id[0]?id:"<empty>");
273 if (ifscreen->result_type != -1)
275 *type = ifscreen->result_type;
278 case INFO_NTYPE_UNKNOWN:
279 add_trace("used", "type", "unknown");
281 case INFO_NTYPE_SUBSCRIBER:
282 add_trace("used", "type", "subscriber");
284 case INFO_NTYPE_NATIONAL:
285 add_trace("used", "type", "national");
287 case INFO_NTYPE_INTERNATIONAL:
288 add_trace("used", "type", "international");
292 if (ifscreen->result_present != -1)
294 *present = ifscreen->result_present;
297 case INFO_PRESENT_ALLOWED:
298 add_trace("used", "present", "allowed");
300 case INFO_PRESENT_RESTRICTED:
301 add_trace("used", "present", "restricted");
303 case INFO_PRESENT_NOTAVAIL:
304 add_trace("used", "present", "not available");
308 if (strchr(ifscreen->match,'%'))
310 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
311 UNCPY(id, ifscreen->result, idsize);
313 if (strchr(ifscreen->result,'%'))
315 *strchr(ifscreen->result,'%') = '\0';
316 UNCAT(id, suffix, idsize);
321 UNCPY(id, ifscreen->result, idsize);
324 add_trace("used", "id", "%s", id[0]?id:"<empty>");
329 /* release call and port (as specified)
331 void EndpointAppPBX::release(int release, int calllocation, int callcause, int portlocation, int portcause)
333 struct port_list *portlist;
334 struct message *message;
337 /* message to test call */
338 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", callcause, calllocation, 0);
340 /* if a release is pending */
341 if (release==RELEASE_CALL || release==RELEASE_ALL || release==RELEASE_PORT_CALLONLY)
343 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (callcause %d location %d)\n", ea_endpoint->ep_serial, callcause, calllocation);
344 if (ea_endpoint->ep_call_id)
346 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_RELEASE);
347 message->param.disconnectinfo.cause = callcause;
348 message->param.disconnectinfo.location = calllocation;
349 message_put(message);
350 ea_endpoint->ep_call_id = 0;
354 if (release != RELEASE_PORT_CALLONLY)
357 call_release(e_hold_id, ea_endpoint->ep_serial, 1, calllocation, callcause);
362 if (release==RELEASE_ALL || release==RELEASE_PORT_CALLONLY)
364 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
365 while((portlist = ea_endpoint->ep_portlist))
367 if (portlist->port_id)
369 SPRINT(cause, "cause_%02x", portcause);
370 set_tone(portlist, cause);
371 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
372 message->param.disconnectinfo.cause = portcause;
373 message->param.disconnectinfo.location = portlocation;
374 message_put(message);
377 ea_endpoint->free_portlist(portlist);
380 /* if callback is enabled, call back with the given caller id */
383 /* reset some stuff */
384 new_state(EPOINT_STATE_IDLE);
385 memset(&e_connectinfo, 0, sizeof(struct connect_info));
386 memset(&e_redirinfo, 0, sizeof(struct redir_info));
387 e_start = e_stop = 0;
388 e_ruleset = ruleset_main;
390 e_rule = e_ruleset->rule_first;
392 e_action_timeout = 0;
394 e_match_to_action = NULL;
396 e_extdialing = e_dialinginfo.id;
403 e_multipoint_cause = CAUSE_NOUSER;
404 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
405 e_dialing_queue[0] = '\0';
407 e_crypt_state = CM_ST_NULL;
408 e_crypt_keyengine_busy = 0;
409 e_crypt_info[0] = '\0';
413 e_tx_state = NOTIFY_STATE_ACTIVE;
414 e_rx_state = NOTIFY_STATE_ACTIVE;
415 e_call_cause = e_call_location = 0;
417 /* the caller info of the callback user */
418 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
419 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
420 /* create dialing by callerinfo */
421 if (e_ext.number[0] && e_extension_interface[0])
423 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
424 /* create callback to the current terminal */
425 SCPY(e_dialinginfo.id, e_ext.number);
426 SCPY(e_dialinginfo.interfaces, e_extension_interface);
427 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
428 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
433 SCPY(e_dialinginfo.id, e_cbto);
436 /* numberrize caller id and use it to dial to the callback */
437 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
439 e_dialinginfo.itype = INFO_ITYPE_ISDN;
440 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
441 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
446 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
447 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
453 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
454 void apply_callerid_restriction(int anon_ignore, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
456 PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d extension='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (extension)?extension:"NULL", (name)?name:"NULL");
458 /* caller id is not restricted, so we do nothing */
459 if (*present != INFO_PRESENT_RESTRICTED)
462 /* only extensions are restricted */
468 /* if we enabled anonymouse ignore */
472 /* else we remove the caller id */
476 *ntype = INFO_NTYPE_UNKNOWN;
478 // *screen = INFO_SCREEN_USER;
479 // maybe we should not make voip address anonymous
482 // maybe it's no fraud to present extension id
484 // extension[0] = '\0';
489 /* used display message to display callerid as available */
490 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *extension, char *name)
492 static char display[81];
495 char *cid = numberrize_callerinfo(id, ntype);
497 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d extension='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (extension)?extension:"NULL", (name)?name:"NULL");
506 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
508 /* internal extension's caller id */
509 if (extension[0] && e_ext.display_int)
512 SCAT(display, extension);
515 if (itype == INFO_ITYPE_VBOX)
516 SCAT(display, "(vbox)");
518 SCAT(display, "(int)");
521 /* external caller id */
522 if (!extension[0] && e_ext.display_ext)
528 if (present == INFO_PRESENT_RESTRICTED)
529 SCAT(display, "anonymous");
531 SCAT(display, "unknown");
538 /* display if callerid is anonymouse but available due anon-ignore */
539 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
542 SCAT(display, "unknown");
545 SCAT(display, " anon");
548 /* display if callerid is anonymouse but available due anon-ignore */
549 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
555 if (present == INFO_PRESENT_RESTRICTED)
556 SCAT(display, "anonymous");
558 SCAT(display, "unknown");
563 SCAT(display, " fake");
567 if (name[0] && e_ext.display_name)
569 if (!display[0] && cid[0])
580 * uses the current state to notify activity
582 void EndpointAppPBX::notify_active(void)
584 struct port_list *portlist = ea_endpoint->ep_portlist;
585 struct message *message;
590 case NOTIFY_STATE_ACTIVE:
591 /* we are already active, so we don't do anything */
594 case NOTIFY_STATE_SUSPEND:
595 notify = INFO_NOTIFY_USER_RESUMED;
598 set_tone(portlist, NULL);
599 portlist = portlist->next;
601 portlist = ea_endpoint->ep_portlist;
604 case NOTIFY_STATE_HOLD:
605 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
608 set_tone(portlist, NULL);
609 portlist = portlist->next;
611 portlist = ea_endpoint->ep_portlist;
614 case NOTIFY_STATE_CONFERENCE:
615 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
618 set_tone(portlist, NULL);
619 portlist = portlist->next;
621 portlist = ea_endpoint->ep_portlist;
625 PERROR("unknown e_tx_state = %d\n", e_tx_state);
631 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
632 message->param.notifyinfo.notify = notify;
633 message_put(message);
635 portlist = portlist->next;
641 * keypad functions during call. one example to use this is to put a call on hold or start a conference
643 void EndpointAppPBX::keypad_function(char digit)
646 /* we must be in a call, in order to send messages to the call */
647 if (e_ext.number[0] == '\0')
649 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
655 /* join conference */
657 if (ea_endpoint->ep_call_id == 0)
659 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
662 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
668 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
672 /* crypt key-exchange */
674 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
680 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
685 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
690 /* set tone pattern for port */
691 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
693 struct message *message;
698 /* store for suspended processes */
703 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no endpoint to notify tone.\n", ea_endpoint->ep_serial);
707 if (e_call_pattern /* pattern are provided */
708 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
709 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
710 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
711 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
712 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
713 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
714 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
715 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
716 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
717 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
718 && tone[0] && !!strncmp(tone,"crypt_*",6))
720 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
726 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
727 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
728 SCPY(message->param.tone.name, tone);
729 message_put(message);
736 * hunts an mISDNport that is available for an outgoing call
737 * if no ifname was given, any interface that is not an extension
740 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
742 struct interface *interface;
743 struct interface_port *ifport, *ifport_start;
744 struct select_channel *selchannel;
745 struct mISDNport *mISDNport;
748 interface = interface_first;
750 /* first find the given interface or, if not given, one with no extension */
755 /* check for given interface */
758 if (!strcasecmp(interface->name, ifname))
760 /* found explicit interface */
761 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
762 add_trace("interface", NULL, "%s", ifname);
769 if (!interface->extension)
771 /* found non extension */
772 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
773 add_trace("interface", NULL, "%s", interface->name);
779 interface = interface->next;
783 /* see if interface has ports */
784 if (!interface->ifport)
787 trace_header("CHANNEL SELECTION (interface has no active ports, skipping)", DIRECTION_NONE);
788 add_trace("interface", NULL, "%s", interface->name);
790 interface = interface->next;
794 /* select port by algorithm */
795 ifport_start = interface->ifport;
797 if (interface->hunt == HUNT_ROUNDROBIN)
799 while(ifport_start->next && index<interface->hunt_next)
801 ifport_start = ifport_start->next;
804 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
805 add_trace("port", NULL, "%d", ifport_start->portnum);
806 add_trace("position", NULL, "%d", index);
811 ifport = ifport_start;
814 /* see if port is available */
815 if (!ifport->mISDNport)
817 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
818 add_trace("port", NULL, "%d", ifport->portnum);
819 add_trace("position", NULL, "%d", index);
823 mISDNport = ifport->mISDNport;
825 /* see if port is administratively blocked */
828 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
829 add_trace("port", NULL, "%d", ifport->portnum);
830 add_trace("position", NULL, "%d", index);
835 /* see if link is up on PTP*/
836 if (mISDNport->ptp && !mISDNport->l2link)
838 trace_header("CHANNEL SELECTION (port is ptp with layer 2 down, skipping)", DIRECTION_NONE);
839 add_trace("port", NULL, "%d", ifport->portnum);
840 add_trace("position", NULL, "%d", index);
845 /* check for channel form selection list */
847 selchannel = ifport->out_channel;
850 switch(selchannel->channel)
852 case CHANNEL_FREE: /* free channel */
853 if (mISDNport->b_reserved >= mISDNport->b_num)
854 break; /* all channel in use or reserverd */
857 while(i < mISDNport->b_num)
859 if (mISDNport->b_port[i] == NULL)
861 *channel = i+1+(i>=15);
862 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
863 add_trace("port", NULL, "%d", ifport->portnum);
864 add_trace("position", NULL, "%d", index);
865 add_trace("channel", NULL, "%d", *channel);
873 case CHANNEL_ANY: /* don't ask for channel */
874 if (mISDNport->b_reserved >= mISDNport->b_num)
876 break; /* all channel in use or reserverd */
878 trace_header("CHANNEL SELECTION (using 'any channel')", DIRECTION_NONE);
879 add_trace("port", NULL, "%d", ifport->portnum);
880 add_trace("position", NULL, "%d", index);
882 *channel = CHANNEL_ANY;
885 case CHANNEL_NO: /* call waiting */
886 trace_header("CHANNEL SELECTION (using 'no channel', call-waiting)", DIRECTION_NONE);
887 add_trace("port", NULL, "%d", ifport->portnum);
888 add_trace("position", NULL, "%d", index);
890 *channel = CHANNEL_NO;
894 if (selchannel->channel<1 || selchannel->channel==16)
895 break; /* invalid channels */
896 i = selchannel->channel-1-(selchannel->channel>=17);
897 if (i >= mISDNport->b_num)
898 break; /* channel not in port */
899 if (mISDNport->b_port[i] == NULL)
901 *channel = selchannel->channel;
902 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
903 add_trace("port", NULL, "%d", ifport->portnum);
904 add_trace("position", NULL, "%d", index);
905 add_trace("channel", NULL, "%d", *channel);
912 break; /* found channel */
913 selchannel = selchannel->next;
916 /* if channel was found, return mISDNport and channel */
919 /* setting next port to start next time */
920 if (interface->hunt == HUNT_ROUNDROBIN)
925 interface->hunt_next = index;
931 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
932 add_trace("port", NULL, "%d", ifport->portnum);
933 add_trace("position", NULL, "%d", index);
937 /* go next port, until all ports are checked */
939 ifport = ifport->next;
943 ifport = interface->ifport;
945 if (ifport != ifport_start)
948 return(NULL); /* no port found */
951 /* outgoing setup to port(s)
952 * ports will be created and a setup is sent if everything is ok. otherwhise
953 * the endpoint is destroyed.
955 void EndpointAppPBX::out_setup(void)
957 struct dialing_info dialinginfo;
959 // class pdss1 *pdss1;
960 struct port_list *portlist;
961 struct message *message;
963 int cause = CAUSE_RESSOURCEUNAVAIL;
966 struct mISDNport *mISDNport;
969 class EndpointAppPBX *atemp;
970 // char allowed_ports[256];
972 char ifname[sizeof(e_ext.interfaces)],
974 struct port_settings port_settings;
978 /* create settings for creating port */
979 memset(&port_settings, 0, sizeof(port_settings));
981 SCPY(port_settings.tones_dir, e_ext.tones_dir);
983 SCPY(port_settings.tones_dir, options.tones_dir);
984 port_settings.tout_setup = e_ext.tout_setup;
985 port_settings.tout_dialing = e_ext.tout_dialing;
986 port_settings.tout_proceeding = e_ext.tout_proceeding;
987 port_settings.tout_alerting = e_ext.tout_alerting;
988 port_settings.tout_disconnect = e_ext.tout_disconnect;
989 // port_settings.tout_hold = e_ext.tout_hold;
990 // port_settings.tout_park = e_ext.tout_park;
991 port_settings.no_seconds = e_ext.no_seconds;
993 /* 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 */
995 /* check what dialinginfo.itype we got */
996 switch(e_dialinginfo.itype)
998 /* *********************** call to extension or vbox */
999 case INFO_ITYPE_ISDN_EXTENSION:
1000 /* check if we deny incoming calls when we use an extension */
1001 if (e_ext.noknocking)
1003 atemp = apppbx_first;
1007 if (!strcmp(atemp->e_ext.number, e_ext.number))
1009 atemp = atemp->next;
1013 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
1014 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ call, port */
1015 return; /* must exit here */
1018 /* FALL THROUGH !!!! */
1019 case INFO_ITYPE_VBOX:
1020 /* get dialed extension's info */
1021 // SCPY(exten, e_dialinginfo.id);
1022 // if (strchr(exten, ','))
1023 // *strchr(exten, ',') = '\0';
1024 // if (!read_extension(&e_ext, exten))
1025 if (!read_extension(&e_ext, e_dialinginfo.id))
1027 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1028 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1029 return; /* must exit here */
1032 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
1034 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
1039 /* string from unconditional call forward (cfu) */
1043 /* present to forwarded party */
1044 if (e_ext.anon_ignore && e_callerinfo.id[0])
1046 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1048 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1052 /* string from busy call forward (cfb) */
1056 class EndpointAppPBX *checkapp = apppbx_first;
1059 if (checkapp != this) /* any other endpoint except our own */
1061 if (!strcmp(checkapp->e_ext.number, e_ext.number))
1063 /* present to forwarded party */
1064 if (e_ext.anon_ignore && e_callerinfo.id[0])
1066 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1068 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1072 checkapp = checkapp->next;
1076 /* string from no-response call forward (cfnr) */
1080 /* when cfnr is done, out_setup() will setup the call */
1083 /* present to forwarded party */
1084 if (e_ext.anon_ignore && e_callerinfo.id[0])
1086 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1090 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1092 e_cfnr_release = now + e_ext.cfnr_delay;
1093 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
1094 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);
1098 /* call to all internal interfaces */
1099 p = e_ext.interfaces;
1100 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple calls for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1104 while(*p!=',' && *p!='\0')
1106 SCCAT(ifname, *p++);
1109 /* found interface */
1110 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
1111 /* hunt for mISDNport and create Port */
1112 mISDNport = hunt_port(ifname, &channel);
1115 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
1116 add_trace("interface", NULL, "%s", ifname);
1120 /* creating INTERNAL port */
1121 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1122 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force);
1124 FATAL("No memory for DSS1 Port instance\n");
1125 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1126 memset(&dialinginfo, 0, sizeof(dialinginfo));
1127 SCPY(dialinginfo.id, e_dialinginfo.id);
1128 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1129 dialinginfo.ntype = e_dialinginfo.ntype;
1130 /* create port_list relation */
1131 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1134 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1136 goto check_anycall_intern;
1138 /* directory.list */
1139 if (e_callerinfo.id[0] && (e_ext.centrex || e_ext.display_name))
1141 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1143 SCPY(e_callerinfo.name, dirname);
1145 // dss1 = (class Pdss1 *)port;
1147 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1148 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1149 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1150 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1151 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1152 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1153 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1154 //terminal if (e_dialinginfo.id)
1155 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1156 /* handle restricted caller ids */
1157 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1158 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1159 /* display callerid if desired for extension */
1160 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.extension, message->param.setup.callerinfo.name));
1161 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1162 /* use cnip, if enabld */
1164 message->param.setup.callerinfo.name[0] = '\0';
1165 /* screen clip if prefix is required */
1166 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1168 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1169 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
1170 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1172 /* use internal caller id */
1173 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1175 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1176 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1178 message_put(message);
1179 logmessage(message);
1183 /* string from parallel call forward (cfp) */
1187 if (e_ext.anon_ignore && e_callerinfo.id[0])
1189 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1193 vbox_only: /* entry point for answering machine only */
1194 cfu_only: /* entry point for cfu */
1195 cfb_only: /* entry point for cfb */
1196 cfnr_only: /* entry point for cfnr */
1197 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1202 /* only if vbox should be dialed, and terminal is given */
1203 if (!strcmp(p, "vbox") && e_ext.number[0])
1205 /* go to the end of p */
1208 /* answering vbox call */
1209 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1211 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1212 FATAL("No memory for VBOX Port instance\n");
1213 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1214 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1218 while(*p!=',' && *p!='\0')
1223 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1224 /* hunt for mISDNport and create Port */
1225 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1228 /* creating EXTERNAL port*/
1229 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1230 if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force)))
1231 FATAL("No memory for DSS1 Port instance\n");
1232 earlyb = mISDNport->earlyb;
1236 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1237 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1243 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1244 goto check_anycall_intern;
1246 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1247 memset(&dialinginfo, 0, sizeof(dialinginfo));
1248 SCPY(dialinginfo.id, cfp);
1249 dialinginfo.itype = INFO_ITYPE_ISDN;
1250 dialinginfo.ntype = e_dialinginfo.ntype;
1251 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1254 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1256 goto check_anycall_intern;
1258 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1259 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1260 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1261 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1262 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1263 /* if clip is hidden */
1264 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1266 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1267 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1268 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1269 message->param.setup.callerinfo.present = e_ext.callerid_present;
1271 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1272 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1273 //terminal if (e_dialinginfo.id)
1274 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1275 /* handle restricted caller ids */
1276 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1277 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1278 /* display callerid if desired for extension */
1279 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.extension, message->param.setup.callerinfo.name));
1280 message_put(message);
1281 logmessage(message);
1285 check_anycall_intern:
1286 /* now we have all ports created */
1289 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1291 if (!ea_endpoint->ep_call_id)
1293 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1294 return; /* must exit here */
1298 /* *********************** external call */
1300 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1301 /* call to extenal interfaces */
1302 p = e_dialinginfo.id;
1306 while(*p!=',' && *p!='\0')
1307 SCCAT(number, *p++);
1311 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");
1312 /* hunt for mISDNport and create Port */
1313 /* hunt for mISDNport and create Port */
1314 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1317 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1318 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1320 goto check_anycall_extern;
1322 /* creating EXTERNAL port*/
1323 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1324 if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force)))
1325 FATAL("No memory for DSS1 Port instance\n");
1326 earlyb = mISDNport->earlyb;
1327 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1328 memset(&dialinginfo, 0, sizeof(dialinginfo));
1329 SCPY(dialinginfo.id, number);
1330 dialinginfo.itype = INFO_ITYPE_ISDN;
1331 dialinginfo.ntype = e_dialinginfo.ntype;
1332 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1335 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1337 goto check_anycall_extern;
1339 // dss1 = (class Pdss1 *)port;
1340 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1341 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1342 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1343 SCPY(message->param.setup.dialinginfo.id, number);
1344 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1345 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1346 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1347 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1348 //terminal if (e_dialinginfo.id)
1349 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1350 /* handle restricted caller ids */
1351 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1352 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1353 /* display callerid if desired for extension */
1354 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.extension, message->param.setup.callerinfo.name));
1355 message_put(message);
1356 logmessage(message);
1360 check_anycall_extern:
1361 /* now we have all ports created */
1364 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1366 if (!ea_endpoint->ep_call_id)
1368 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1369 return; /* must exit here */
1377 /* handler for endpoint
1381 int EndpointAppPBX::handler(void)
1383 if (e_crypt_state!=CM_ST_NULL)
1388 /* process answering machine (play) handling */
1391 if (e_action->index == ACTION_VBOX_PLAY)
1394 /* process action timeout */
1395 if (e_action_timeout)
1396 if (now_d >= e_action_timeout)
1398 if (e_state!=EPOINT_STATE_CONNECT)
1401 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1402 e_multipoint_cause = CAUSE_NOUSER;
1403 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
1404 new_state(EPOINT_STATE_IN_OVERLAP);
1407 return(1); /* we must exit, because our endpoint might be gone */
1409 e_action_timeout = 0;
1412 /* process action timeout */
1413 if (e_match_timeout)
1414 if (now_d >= e_match_timeout)
1417 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1419 return(1); /* we must exit, because our endpoint might be gone */
1424 /* process redialing (epoint redials to port) */
1427 if (now_d >= e_redial)
1430 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1432 new_state(EPOINT_STATE_OUT_SETUP);
1433 /* call special setup routine */
1440 /* process powerdialing (epoint redials to epoint) */
1441 if (e_powerdialing > 0)
1443 if (now_d >= e_powerdialing)
1445 e_powerdialing = -1; /* leave power dialing on */
1446 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1449 e_ruleset = ruleset_main;
1451 e_rule = e_ruleset->rule_first;
1453 new_state(EPOINT_STATE_IN_OVERLAP);
1459 /* process call forward no response */
1462 struct port_list *portlist;
1463 struct message *message;
1465 if (now >= e_cfnr_release)
1467 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1470 /* release all ports */
1471 while((portlist = ea_endpoint->ep_portlist))
1473 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1474 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1475 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1476 message_put(message);
1477 logmessage(message);
1478 ea_endpoint->free_portlist(portlist);
1481 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
1482 message->param.channel = CHANNEL_STATE_HOLD;
1483 message_put(message);
1484 /* indicate no patterns */
1485 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
1486 message_put(message);
1487 /* set setup state, since we have no response from the new call */
1488 new_state(EPOINT_STATE_OUT_SETUP);
1493 if (now >= e_cfnr_call)
1495 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1501 /* handle connection to user */
1502 if (e_state == EPOINT_STATE_IDLE)
1504 /* epoint is idle, check callback */
1506 if (now_d >= e_callback)
1508 e_callback = 0; /* done with callback */
1509 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1510 new_state(EPOINT_STATE_OUT_SETUP);
1516 /* check for password timeout */
1518 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1520 struct port_list *portlist;
1522 if (now >= e_password_timeout)
1524 e_ruleset = ruleset_main;
1526 e_rule = e_ruleset->rule_first;
1528 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1529 trace_header("PASSWORD timeout", DIRECTION_NONE);
1531 e_connectedmode = 0;
1533 new_state(EPOINT_STATE_OUT_DISCONNECT);
1534 portlist = ea_endpoint->ep_portlist;
1537 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1538 set_tone(portlist, "cause_10");
1548 /* doing a hookflash */
1549 void EndpointAppPBX::hookflash(void)
1553 /* be sure that we are active */
1555 e_tx_state = NOTIFY_STATE_ACTIVE;
1557 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1559 if (ea_endpoint->ep_use > 1)
1561 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1564 /* dialtone after pressing the hash key */
1565 process_hangup(e_call_cause, e_call_location);
1566 e_multipoint_cause = CAUSE_NOUSER;
1567 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
1568 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1571 port->set_echotest(0);
1573 if (ea_endpoint->ep_call_id)
1575 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1577 e_ruleset = ruleset_main;
1579 e_rule = e_ruleset->rule_first;
1581 new_state(EPOINT_STATE_IN_OVERLAP);
1582 e_connectedmode = 1;
1583 SCPY(e_dialinginfo.id, e_ext.prefix);
1584 e_extdialing = e_dialinginfo.id;
1586 if (e_dialinginfo.id[0])
1588 set_tone(ea_endpoint->ep_portlist, "dialing");
1592 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1599 /* messages from port
1601 /* port MESSAGE_SETUP */
1602 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1604 struct message *message;
1606 int writeext; /* flags need to write extension after modification */
1608 struct interface *interface;
1610 portlist->port_type = param->setup.port_type;
1611 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1612 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1613 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1614 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1615 e_dtmf = param->setup.dtmf;
1617 /* screen incoming caller id */
1618 interface = interface_first;
1621 if (!strcmp(e_callerinfo.interface, interface->name))
1625 interface = interface->next;
1628 screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1630 /* process extension */
1631 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1633 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1634 /* port makes call from extension */
1635 SCPY(e_callerinfo.extension, e_callerinfo.id);
1636 SCPY(e_ext.number, e_callerinfo.extension);
1637 SCPY(e_extension_interface, e_callerinfo.interface);
1640 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1642 trace_header("SETUP", DIRECTION_IN);
1643 if (e_callerinfo.extension[0])
1644 add_trace("extension", NULL, "%s", e_callerinfo.extension);
1645 add_trace("caller id", "number", "%s", numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype));
1646 if (e_callerinfo.present == INFO_PRESENT_RESTRICTED)
1647 add_trace("caller id", "present", "restricted");
1648 if (e_redirinfo.id[0])
1650 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(e_redirinfo.id, e_redirinfo.ntype));
1651 if (e_redirinfo.present == INFO_PRESENT_RESTRICTED)
1652 add_trace("redir'ing", "present", "restricted");
1654 if (e_dialinginfo.id)
1655 add_trace("dialing", "number", "%s", e_dialinginfo.id);
1658 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1660 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1662 /* get extension's info about caller */
1663 if (!read_extension(&e_ext, e_ext.number))
1665 /* extension doesn't exist */
1666 trace_header("EXTENSION (not created)", DIRECTION_IN);
1667 add_trace("extension", NULL, "%s", e_ext.number);
1669 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1670 new_state(EPOINT_STATE_OUT_DISCONNECT);
1671 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1672 e_ext.number[0] = '\0'; /* no terminal */
1677 /* put prefix (next) in front of e_dialinginfo.id */
1680 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1681 SCPY(e_dialinginfo.id, buffer);
1682 e_ext.next[0] = '\0';
1684 } else if (e_ext.prefix[0])
1686 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1687 SCPY(e_dialinginfo.id, buffer);
1690 /* screen caller id by extension's config */
1691 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1693 SCPY(e_callerinfo.name, e_ext.name);
1694 /* use caller id (or if exist: id_next_call) for this call */
1695 if (e_ext.id_next_call_present >= 0)
1697 SCPY(e_callerinfo.id, e_ext.id_next_call);
1698 /* if we restrict the pesentation */
1699 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1700 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1701 else e_callerinfo.present = e_ext.id_next_call_present;
1702 e_callerinfo.ntype = e_ext.id_next_call_type;
1703 e_ext.id_next_call_present = -1;
1707 SCPY(e_callerinfo.id, e_ext.callerid);
1708 /* if we restrict the pesentation */
1709 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1710 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1711 else e_callerinfo.present = e_ext.callerid_present;
1712 e_callerinfo.ntype = e_ext.callerid_type;
1715 /* extension is written */
1717 write_extension(&e_ext, e_ext.number);
1719 /* set volume of rx and tx */
1720 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1721 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
1723 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1724 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1725 message->param.mISDNsignal.rxvol = e_ext.txvol;
1726 message->param.mISDNsignal.txvol = e_ext.rxvol;
1727 message_put(message);
1730 /* start recording if enabled */
1731 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1733 /* check if we are a terminal */
1734 if (e_ext.number[0] == '\0')
1735 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1738 port = find_port_id(portlist->port_id);
1740 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1745 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1746 /* no terminal identification */
1747 e_ext.number[0] = '\0';
1748 e_extension_interface[0] = '\0';
1749 memset(&e_ext, 0, sizeof(e_ext));
1750 e_ext.rights = 4; /* right to dial internat */
1754 e_ruleset = ruleset_main;
1756 e_rule = e_ruleset->rule_first;
1758 e_extdialing = e_dialinginfo.id;
1759 new_state(EPOINT_STATE_IN_SETUP);
1760 if (e_dialinginfo.id[0])
1762 set_tone(portlist, "dialing");
1765 if (e_ext.number[0])
1766 set_tone(portlist, "dialpbx");
1768 set_tone(portlist, "dialtone");
1771 if (e_state == EPOINT_STATE_IN_SETUP)
1773 /* request MORE info, if not already at higher state */
1774 new_state(EPOINT_STATE_IN_OVERLAP);
1775 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1776 message_put(message);
1777 logmessage(message);
1781 /* port MESSAGE_INFORMATION */
1782 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1784 trace_header("INFORMATION", DIRECTION_IN);
1785 add_trace("dialing", NULL, "%s", param->information.id);
1786 if (param->information.sending_complete)
1787 add_trace("complete", NULL, NULL);
1791 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1794 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.id, e_ext.number, e_callerinfo.id);
1798 /* if vbox_play is done, the information are just used as they come */
1800 if (e_action->index == ACTION_VBOX_PLAY)
1802 /* concat dialing string */
1803 SCAT(e_dialinginfo.id, param->information.id);
1808 /* keypad when disconnect but in connected mode */
1809 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1811 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1812 /* processing keypad function */
1813 if (param->information.id[0] == '0')
1820 /* keypad when connected */
1821 if (e_state == EPOINT_STATE_CONNECT && e_ext.keypad)
1823 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1824 /* processing keypad function */
1825 if (param->information.id[0] == '0')
1829 if (param->information.id[0])
1830 keypad_function(param->information.id[0]);
1833 if (e_state != EPOINT_STATE_IN_OVERLAP)
1835 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in overlap, or connect state.\n", ea_endpoint->ep_serial);
1838 if (!param->information.id[0])
1840 if (e_dialinginfo.id[0]=='\0' && !e_action)
1842 set_tone(portlist, "dialing");
1845 if (e_action->index==ACTION_OUTDIAL
1846 || e_action->index==ACTION_EXTERNAL)
1849 set_tone(portlist, "dialing");
1850 else if (!e_extdialing[0])
1851 set_tone(portlist, "dialing");
1853 /* concat dialing string */
1854 SCAT(e_dialinginfo.id, param->information.id);
1858 /* port MESSAGE_DTMF */
1859 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1861 trace_header("DTMF", DIRECTION_IN);
1862 add_trace("digit", NULL, "%c", param->dtmf);
1864 /* only if dtmf detection is enabled */
1867 PDEBUG(DEBUG_EPOINT, "dtmf detection is disabled\n");
1872 NOTE: vbox is now handled due to overlap state
1873 /* if vbox_play is done, the dtmf digits are just used as they come */
1875 if (e_action->index == ACTION_VBOX_PLAY)
1877 /* concat dialing string */
1878 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1880 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1881 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1884 /* continue to process *X# sequences */
1888 /* check for *X# sequence */
1889 if (e_state == EPOINT_STATE_CONNECT)
1891 if (e_dtmf_time+3 < now)
1893 /* the last digit was too far in the past to be a sequence */
1894 if (param->dtmf == '*')
1895 /* only start is allowed in the sequence */
1901 /* we have a sequence of digits, see what we got */
1902 if (param->dtmf == '*')
1904 else if (param->dtmf>='0' && param->dtmf<='9')
1906 /* we need to have a star before we receive the digit of the sequence */
1907 if (e_dtmf_last == '*')
1908 e_dtmf_last = param->dtmf;
1909 } else if (param->dtmf == '#')
1912 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1914 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1915 if (e_dtmf_last == '0')
1920 /* processing keypad function */
1922 keypad_function(e_dtmf_last);
1928 /* set last time of dtmf */
1933 /* check for ## hookflash during dialing */
1935 if (e_action->index==ACTION_PASSWORD
1936 || e_action->index==ACTION_PASSWORD_WRITE)
1938 if (param->dtmf=='#') /* current digit is '#' */
1940 if (e_state==EPOINT_STATE_IN_DISCONNECT
1941 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1958 /* dialing using dtmf digit */
1959 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1961 if (e_dialinginfo.id[0]=='\0' && !e_action)
1963 set_tone(portlist, "dialing");
1965 /* concat dialing string */
1966 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1968 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1969 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1975 /* port MESSAGE_CRYPT */
1976 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1978 /* send crypt response to cryptman */
1979 if (param->crypt.type == CR_MESSAGE_IND)
1980 cryptman_msg2man(param->crypt.data, param->crypt.len);
1982 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1985 /* port MESSAGE_OVERLAP */
1986 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1988 struct message *message;
1990 /* signal to call tool */
1991 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1993 trace_header("SETUP ACKNOWLEDGE", DIRECTION_IN);
1995 if (e_dialing_queue[0] && portlist)
1997 /* send what we have not dialed yet, because we had no setup complete */
1998 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1999 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2000 SCPY(message->param.information.id, e_dialing_queue);
2001 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
2002 message_put(message);
2003 logmessage(message);
2004 e_dialing_queue[0] = '\0';
2006 /* check if pattern is available */
2007 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
2009 /* indicate patterns */
2010 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2011 message_put(message);
2013 /* connect audio, if not already */
2014 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2015 message->param.channel = CHANNEL_STATE_CONNECT;
2016 message_put(message);
2019 /* indicate no patterns */
2020 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
2021 message_put(message);
2023 /* disconnect audio, if not already */
2024 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2025 message->param.channel = CHANNEL_STATE_HOLD;
2026 message_put(message);
2028 new_state(EPOINT_STATE_OUT_OVERLAP);
2029 /* if we are in a call */
2030 if (ea_endpoint->ep_call_id)
2032 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2033 memcpy(&message->param, param, sizeof(union parameter));
2034 message_put(message);
2038 /* port MESSAGE_PROCEEDING */
2039 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2041 struct message *message;
2043 /* signal to call tool */
2044 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
2046 trace_header("PROCEEDING", DIRECTION_IN);
2048 e_state = EPOINT_STATE_OUT_PROCEEDING;
2049 /* check if pattern is availatle */
2050 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2052 /* indicate patterns */
2053 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2054 message_put(message);
2056 /* connect audio, if not already */
2057 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2058 message->param.channel = CHANNEL_STATE_CONNECT;
2059 message_put(message);
2062 /* indicate no patterns */
2063 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
2064 message_put(message);
2066 /* disconnect audio, if not already */
2067 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2068 message->param.channel = CHANNEL_STATE_HOLD;
2069 message_put(message);
2071 /* if we are in a call */
2072 if (ea_endpoint->ep_call_id)
2074 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2075 memcpy(&message->param, param, sizeof(union parameter));
2076 message_put(message);
2080 /* port MESSAGE_ALERTING */
2081 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
2083 struct message *message;
2085 /* signal to call tool */
2086 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
2088 trace_header("ALERTING", DIRECTION_IN);
2090 new_state(EPOINT_STATE_OUT_ALERTING);
2091 /* check if pattern is available */
2092 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2094 /* indicate patterns */
2095 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2096 message_put(message);
2098 /* connect audio, if not already */
2099 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2100 message->param.channel = CHANNEL_STATE_CONNECT;
2101 message_put(message);
2104 /* indicate no patterns */
2105 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
2106 message_put(message);
2108 /* disconnect audio, if not already */
2109 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2110 message->param.channel = CHANNEL_STATE_HOLD;
2111 message_put(message);
2113 /* if we are in a call */
2114 if (ea_endpoint->ep_call_id)
2116 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2117 memcpy(&message->param, param, sizeof(union parameter));
2118 message_put(message);
2122 /* port MESSAGE_CONNECT */
2123 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2125 struct message *message;
2127 unsigned long port_id = portlist->port_id;
2128 struct port_list *tportlist;
2130 struct interface *interface;
2132 /* signal to call tool */
2133 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2135 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2136 trace_header("CONNECT", DIRECTION_IN);
2137 if (e_connectinfo.extension[0])
2138 add_trace("extension", NULL, "%s", e_connectinfo.extension);
2139 add_trace("connect id", "number", "%s", numberrize_callerinfo(e_connectinfo.id, e_connectinfo.ntype));
2140 if (e_connectinfo.present == INFO_PRESENT_RESTRICTED)
2141 add_trace("connect id", "present", "restricted");
2143 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2144 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2146 tportlist = ea_endpoint->ep_portlist;
2147 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2148 tportlist = tportlist->next;
2149 if (tportlist->port_id == port_id)
2150 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2151 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2152 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2153 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2154 message_put(message);
2155 logmessage(message);
2156 ea_endpoint->free_portlist(tportlist);
2158 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2162 /* screen incoming connected id */
2163 interface = interface_first;
2166 if (!strcmp(e_connectinfo.interface, interface->name))
2170 interface = interface->next;
2173 screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2175 /* screen connected name */
2177 SCPY(e_connectinfo.name, e_ext.name);
2179 /* add internal id to colp */
2180 SCPY(e_connectinfo.extension, e_ext.number);
2182 /* we store the connected port number */
2183 SCPY(e_extension_interface, e_connectinfo.interface);
2185 /* for internal and am calls, we get the extension's id */
2186 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2188 SCPY(e_connectinfo.id, e_ext.callerid);
2189 SCPY(e_connectinfo.extension, e_ext.number);
2190 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2191 e_connectinfo.ntype = e_ext.callerid_type;
2192 e_connectinfo.present = e_ext.callerid_present;
2194 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2196 e_connectinfo.itype = INFO_ITYPE_VBOX;
2197 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2200 new_state(EPOINT_STATE_CONNECT);
2202 /* set volume of rx and tx */
2203 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2205 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2206 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2207 message->param.mISDNsignal.rxvol = e_ext.txvol;
2208 message->param.mISDNsignal.txvol = e_ext.rxvol;
2209 message_put(message);
2212 e_cfnr_call = e_cfnr_release = 0;
2213 if (e_ext.number[0])
2214 e_dtmf = 1; /* allow dtmf */
2215 // if (call_countrelations(ea_endpoint->ep_call_id) == 2)
2218 /* other calls with no caller id (or not available for the extension) and force colp */
2219 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2221 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2222 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2224 port = find_port_id(portlist->port_id);
2227 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype));
2228 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2232 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2233 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2234 message_put(message);
2236 if (ea_endpoint->ep_call_id)
2238 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2239 message->param.channel = CHANNEL_STATE_CONNECT;
2240 message_put(message);
2241 } else if (!e_adminid)
2244 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2245 SCPY(e_ext.number, e_cbcaller);
2246 new_state(EPOINT_STATE_IN_OVERLAP);
2247 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2249 /* get extension's info about terminal */
2250 if (!read_extension(&e_ext, e_ext.number))
2252 /* extension doesn't exist */
2253 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2254 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2255 new_state(EPOINT_STATE_OUT_DISCONNECT);
2256 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2260 /* put prefix in front of e_cbdialing */
2261 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2262 SCPY(e_dialinginfo.id, buffer);
2263 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2264 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2266 /* use caller id (or if exist: id_next_call) for this call */
2267 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2268 SCPY(e_callerinfo.extension, e_ext.number);
2269 if (e_ext.id_next_call_present >= 0)
2271 SCPY(e_callerinfo.id, e_ext.id_next_call);
2272 e_callerinfo.present = e_ext.id_next_call_present;
2273 e_callerinfo.ntype = e_ext.id_next_call_type;
2274 e_ext.id_next_call_present = -1;
2275 /* extension is written */
2276 write_extension(&e_ext, e_ext.number);
2279 SCPY(e_callerinfo.id, e_ext.callerid);
2280 e_callerinfo.present = e_ext.callerid_present;
2281 e_callerinfo.ntype = e_ext.callerid_type;
2284 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2287 /* check if caller id is NOT authenticated */
2288 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2290 /* make call state to enter password */
2291 new_state(EPOINT_STATE_IN_OVERLAP);
2292 e_action = &action_password_write;
2293 e_match_timeout = 0;
2294 e_match_to_action = NULL;
2295 e_dialinginfo.id[0] = '\0';
2296 e_extdialing = strchr(e_dialinginfo.id, '\0');
2297 e_password_timeout = now+20;
2301 /* incoming call (callback) */
2302 e_ruleset = ruleset_main;
2304 e_rule = e_ruleset->rule_first;
2306 e_extdialing = e_dialinginfo.id;
2307 if (e_dialinginfo.id[0])
2309 set_tone(portlist, "dialing");
2313 set_tone(portlist, "dialpbx");
2316 } else /* testcall */
2318 set_tone(portlist, "hold");
2321 /* start recording if enabled, not when answering machine answers */
2322 if (param->connectinfo.itype!=INFO_ITYPE_VBOX && e_ext.number[0] && e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
2324 /* check if we are a terminal */
2325 if (e_ext.number[0] == '\0')
2326 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2329 port = find_port_id(portlist->port_id);
2331 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2336 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2337 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2339 struct message *message;
2341 unsigned long port_id = portlist->port_id;
2345 /* signal to call tool */
2346 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2348 trace_header((message_type==MESSAGE_DISCONNECT)?(char *)"DISCONNECT":(char *)"RELEASE", DIRECTION_IN);
2349 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
2350 add_trace("cause", "location", "%d", param->disconnectinfo.location);
2353 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2354 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2356 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2361 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);
2362 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2363 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2365 /* check if we have more than one portlist relation and we just ignore the disconnect */
2366 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2368 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2369 portlist = ea_endpoint->ep_portlist;
2372 if (portlist->port_id == port_id)
2374 portlist = portlist->next;
2377 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2378 if (message_type != MESSAGE_RELEASE)
2380 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2381 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2382 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2383 message_put(message);
2384 logmessage(message);
2386 ea_endpoint->free_portlist(portlist);
2387 return; /* one relation removed */
2389 if (e_state == EPOINT_STATE_CONNECT)
2391 /* use cause from port after connect */
2392 cause = param->disconnectinfo.cause;
2393 location = param->disconnectinfo.location;
2396 /* use multipoint cause if no connect yet */
2397 cause = e_multipoint_cause;
2398 location = e_multipoint_location;
2401 e_cfnr_call = e_cfnr_release = 0;
2403 /* process hangup */
2404 process_hangup(e_call_cause, e_call_location);
2405 e_multipoint_cause = 0;
2406 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
2408 /* tone to disconnected end */
2409 SPRINT(buffer, "cause_%02x", cause);
2410 if (ea_endpoint->ep_portlist)
2411 set_tone(ea_endpoint->ep_portlist, buffer);
2413 new_state(EPOINT_STATE_IN_DISCONNECT);
2414 if (ea_endpoint->ep_call_id)
2416 int haspatterns = 0;
2417 /* check if pattern is available */
2418 if (ea_endpoint->ep_portlist)
2419 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2420 if (callpbx_countrelations(ea_endpoint->ep_call_id)==2 // we must count relations, in order not to disturb the conference ; NOTE: asterisk always counts two, since it is a point to point call
2421 && message_type != MESSAGE_RELEASE) // if we release, we are done
2425 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2426 /* indicate patterns */
2427 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2428 message_put(message);
2429 /* connect audio, if not already */
2430 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2431 message->param.channel = CHANNEL_STATE_CONNECT;
2432 message_put(message);
2433 /* send disconnect */
2434 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2435 memcpy(&message->param, param, sizeof(union parameter));
2436 message_put(message);
2437 /* disable encryption if disconnected */
2438 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2440 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2444 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2447 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2448 return; /* must exit here */
2451 /* port MESSAGE_TIMEOUT */
2452 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2456 trace_header("TIMEOUT", DIRECTION_IN);
2457 message_type = MESSAGE_DISCONNECT;
2458 switch (param->state)
2460 case PORT_STATE_OUT_SETUP:
2461 case PORT_STATE_OUT_OVERLAP:
2462 add_trace("state", NULL, "outgoing setup/dialing");
2464 /* no user responding */
2465 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2466 return; /* must exit here */
2468 case PORT_STATE_IN_SETUP:
2469 case PORT_STATE_IN_OVERLAP:
2470 add_trace("state", NULL, "incoming setup/dialing");
2471 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2472 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2475 case PORT_STATE_OUT_PROCEEDING:
2476 add_trace("state", NULL, "outgoing proceeding");
2478 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2479 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2480 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2481 return; /* must exit here */
2483 case PORT_STATE_IN_PROCEEDING:
2484 add_trace("state", NULL, "incoming proceeding");
2485 param->disconnectinfo.cause = CAUSE_NOUSER;
2486 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2489 case PORT_STATE_OUT_ALERTING:
2490 add_trace("state", NULL, "outgoing alerting");
2492 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2493 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2494 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2495 return; /* must exit here */
2497 case PORT_STATE_IN_ALERTING:
2498 add_trace("state", NULL, "incoming alerting");
2499 param->disconnectinfo.cause = CAUSE_NOANSWER;
2500 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2503 case PORT_STATE_IN_DISCONNECT:
2504 case PORT_STATE_OUT_DISCONNECT:
2505 add_trace("state", NULL, "disconnect");
2507 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2508 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2509 return; /* must exit here */
2512 param->disconnectinfo.cause = 31; /* normal unspecified */
2513 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2516 /* release call, disconnect isdn */
2518 new_state(EPOINT_STATE_OUT_DISCONNECT);
2519 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2520 SCPY(e_tone, cause);
2523 set_tone(portlist, cause);
2524 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2525 portlist = portlist->next;
2527 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
2530 /* port MESSAGE_NOTIFY */
2531 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2533 struct message *message;
2537 /* signal to call tool */
2538 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2539 if (param->notifyinfo.notify)
2541 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2544 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2545 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2547 case INFO_NOTIFY_REMOTE_HOLD:
2548 case INFO_NOTIFY_USER_SUSPENDED:
2549 /* tell call about it */
2550 if (ea_endpoint->ep_call_id)
2552 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2553 message->param.channel = CHANNEL_STATE_HOLD;
2554 message_put(message);
2558 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2559 case INFO_NOTIFY_USER_RESUMED:
2560 /* set volume of rx and tx */
2561 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2562 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2565 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2566 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2567 message->param.mISDNsignal.rxvol = e_ext.txvol;
2568 message->param.mISDNsignal.txvol = e_ext.rxvol;
2569 message_put(message);
2571 /* set current tone */
2573 set_tone(portlist, e_tone);
2574 /* tell call about it */
2575 if (ea_endpoint->ep_call_id)
2577 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2578 message->param.channel = CHANNEL_STATE_CONNECT;
2579 message_put(message);
2584 /* get name of notify */
2585 switch(param->notifyinfo.notify)
2591 logtext = "USER_SUSPENDED";
2594 logtext = "BEARER_SERVICE_CHANGED";
2597 logtext = "USER_RESUMED";
2600 logtext = "CONFERENCE_ESTABLISHED";
2603 logtext = "CONFERENCE_DISCONNECTED";
2606 logtext = "OTHER_PARTY_ADDED";
2609 logtext = "ISOLATED";
2612 logtext = "REATTACHED";
2615 logtext = "OTHER_PARTY_ISOLATED";
2618 logtext = "OTHER_PARTY_REATTACHED";
2621 logtext = "OTHER_PARTY_SPLIT";
2624 logtext = "OTHER_PARTY_DISCONNECTED";
2627 logtext = "CONFERENCE_FLOATING";
2630 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2633 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2636 logtext = "CALL_IS_A_WAITING_CALL";
2639 logtext = "DIVERSION_ACTIVATED";
2642 logtext = "RESERVED_CT_1";
2645 logtext = "RESERVED_CT_2";
2648 logtext = "REVERSE_CHARGING";
2651 logtext = "REMOTE_HOLD";
2654 logtext = "REMOTE_RETRIEVAL";
2657 logtext = "CALL_IS_DIVERTING";
2660 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2664 trace_header("NOTIFY", DIRECTION_IN);
2665 if (param->notifyinfo.notify)
2666 add_trace("indicator", NULL, "%s", logtext);
2667 if (param->notifyinfo.id)
2669 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype));
2670 if (param->notifyinfo.present == INFO_PRESENT_RESTRICTED)
2671 add_trace("redir'on", "present", "restricted");
2673 if (param->notifyinfo.display[0])
2674 add_trace("display", NULL, "%s", param->notifyinfo.display);
2677 /* notify call if available */
2678 if (ea_endpoint->ep_call_id)
2680 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOTIFY);
2681 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2682 message_put(message);
2687 /* port MESSAGE_FACILITY */
2688 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2690 struct message *message;
2692 trace_header("FACILITY", DIRECTION_IN);
2695 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_FACILITY);
2696 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2697 message_put(message);
2700 /* port MESSAGE_SUSPEND */
2701 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2702 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2704 trace_header("SUSPEND", DIRECTION_IN);
2706 /* epoint is now parked */
2707 ea_endpoint->ep_park = 1;
2708 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2709 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2711 /* remove port relation */
2712 ea_endpoint->free_portlist(portlist);
2715 /* port MESSAGE_RESUME */
2716 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2717 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2719 trace_header("RESUME", DIRECTION_IN);
2721 /* epoint is now resumed */
2722 ea_endpoint->ep_park = 0;
2727 /* port sends message to the endpoint
2729 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2731 struct port_list *portlist;
2732 struct message *message;
2734 portlist = ea_endpoint->ep_portlist;
2737 if (port_id == portlist->port_id)
2739 portlist = portlist->next;
2743 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);
2747 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2748 switch(message_type)
2750 case MESSAGE_DATA: /* data from port */
2751 /* check if there is a call */
2752 if (!ea_endpoint->ep_call_id)
2754 /* continue if only one portlist */
2755 if (ea_endpoint->ep_portlist->next != NULL)
2757 /* forward message */
2758 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, param);
2761 case MESSAGE_TONE_EOF: /* tone is end of file */
2762 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2765 if (e_action->index == ACTION_VBOX_PLAY)
2769 if (e_action->index == ACTION_EFI)
2776 case MESSAGE_TONE_COUNTER: /* counter info received */
2777 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);
2779 if (e_action->index == ACTION_VBOX_PLAY)
2781 e_vbox_counter = param->counter.current;
2782 if (param->counter.max >= 0)
2783 e_vbox_counter_max = param->counter.max;
2787 /* PORT sends SETUP message */
2789 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call from callerid=%s, dialing=%s\n", ea_endpoint->ep_serial, param->setup.callerinfo.id, param->setup.dialinginfo.id);
2790 if (e_state!=EPOINT_STATE_IDLE)
2792 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2795 port_setup(portlist, message_type, param);
2798 /* PORT sends INFORMATION message */
2799 case MESSAGE_INFORMATION: /* additional digits received */
2800 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call dialing more=%s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->information.id, e_ext.number, e_callerinfo.id);
2801 port_information(portlist, message_type, param);
2804 /* PORT sends FACILITY message */
2805 case MESSAGE_FACILITY:
2806 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2807 port_facility(portlist, message_type, param);
2810 /* PORT sends DTMF message */
2811 case MESSAGE_DTMF: /* dtmf digits received */
2812 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf digit=%c (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->dtmf, e_ext.number, e_callerinfo.id);
2813 port_dtmf(portlist, message_type, param);
2816 /* PORT sends CRYPT message */
2817 case MESSAGE_CRYPT: /* crypt response received */
2818 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2819 port_crypt(portlist, message_type, param);
2822 /* PORT sends MORE message */
2823 case MESSAGE_OVERLAP:
2824 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is accepted [overlap dialing] (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2825 if (e_state != EPOINT_STATE_OUT_SETUP)
2827 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);
2830 port_overlap(portlist, message_type, param);
2833 /* PORT sends PROCEEDING message */
2834 case MESSAGE_PROCEEDING: /* port is proceeding */
2835 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is proceeding (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2836 if (e_state!=EPOINT_STATE_OUT_SETUP
2837 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2839 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);
2842 port_proceeding(portlist, message_type, param);
2845 /* PORT sends ALERTING message */
2846 case MESSAGE_ALERTING:
2847 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is ringing (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2848 if (e_state!=EPOINT_STATE_OUT_SETUP
2849 && e_state!=EPOINT_STATE_OUT_OVERLAP
2850 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2852 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);
2855 port_alerting(portlist, message_type, param);
2858 /* PORT sends CONNECT message */
2859 case MESSAGE_CONNECT:
2860 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call connected to %s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_connectinfo.id, e_ext.number, e_callerinfo.id);
2861 if (e_state!=EPOINT_STATE_OUT_SETUP
2862 && e_state!=EPOINT_STATE_OUT_OVERLAP
2863 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2864 && e_state!=EPOINT_STATE_OUT_ALERTING)
2866 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2869 port_connect(portlist, message_type, param);
2872 /* PORT sends DISCONNECT message */
2873 case MESSAGE_DISCONNECT: /* port is disconnected */
2874 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call disconnect with cause=%d location=%d (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->disconnectinfo.cause, param->disconnectinfo.location, e_ext.number, e_callerinfo.id);
2875 port_disconnect_release(portlist, message_type, param);
2878 /* PORT sends a RELEASE message */
2879 case MESSAGE_RELEASE: /* port releases */
2880 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) release with cause=%d location=%d (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->disconnectinfo.cause, param->disconnectinfo.location, e_ext.number, e_callerinfo.id);
2881 /* portlist is release at port_disconnect_release, thanx Paul */
2882 port_disconnect_release(portlist, message_type, param);
2885 /* PORT sends a TIMEOUT message */
2886 case MESSAGE_TIMEOUT:
2887 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received timeout (state=%d).\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->state);
2888 port_timeout(portlist, message_type, param);
2889 break; /* release */
2891 /* PORT sends a NOTIFY message */
2892 case MESSAGE_NOTIFY:
2893 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2894 port_notify(portlist, message_type, param);
2897 /* PORT sends a SUSPEND message */
2898 case MESSAGE_SUSPEND:
2899 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received suspend.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2900 port_suspend(portlist, message_type, param);
2901 break; /* suspend */
2903 /* PORT sends a RESUME message */
2904 case MESSAGE_RESUME:
2905 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received resume.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2906 port_resume(portlist, message_type, param);
2910 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message);
2913 /* Note: this endpoint may be destroyed, so we MUST return */
2917 /* messages from port
2919 /* call MESSAGE_CRYPT */
2920 void EndpointAppPBX::call_crypt(struct port_list *portlist, int message_type, union parameter *param)
2922 switch(param->crypt.type)
2924 /* message from remote port to "crypt manager" */
2925 case CU_ACTK_REQ: /* activate key-exchange */
2926 case CU_ACTS_REQ: /* activate shared key */
2927 case CU_DACT_REQ: /* deactivate */
2928 case CU_INFO_REQ: /* request last info message */
2929 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2932 /* message from "crypt manager" to user */
2933 case CU_ACTK_CONF: /* key-echange done */
2934 case CU_ACTS_CONF: /* shared key done */
2935 case CU_DACT_CONF: /* deactivated */
2936 case CU_DACT_IND: /* deactivated */
2937 case CU_ERROR_IND: /* receive error message */
2938 case CU_INFO_IND: /* receive info message */
2939 case CU_INFO_CONF: /* receive info message */
2940 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2944 PERROR("EPOINT(%d) epoint with terminal '%s' (caller id '%s') unknown crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
2948 /* call MESSAGE_INFORMATION */
2949 void EndpointAppPBX::call_information(struct port_list *portlist, int message_type, union parameter *param)
2951 struct message *message;
2957 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2958 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2959 message_put(message);
2960 logmessage(message);
2961 portlist = portlist->next;
2965 /* call MESSAGE_FACILITY */
2966 void EndpointAppPBX::call_facility(struct port_list *portlist, int message_type, union parameter *param)
2968 struct message *message;
2970 if (!e_ext.facility)
2977 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2978 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2979 message_put(message);
2980 logmessage(message);
2981 portlist = portlist->next;
2985 /* call MESSAGE_MORE */
2986 void EndpointAppPBX::call_overlap(struct port_list *portlist, int message_type, union parameter *param)
2988 struct message *message;
2990 new_state(EPOINT_STATE_IN_OVERLAP);
2993 if (e_call_pattern && e_ext.own_setup)
2995 /* disconnect audio */
2996 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2997 message->param.channel = CHANNEL_STATE_HOLD;
2998 message_put(message);
3000 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3002 set_tone(portlist, "dialtone");
3005 if (e_ext.number[0])
3006 set_tone(portlist, "dialpbx");
3008 set_tone(portlist, "dialtone");
3011 /* call MESSAGE_PROCEEDING */
3012 void EndpointAppPBX::call_proceeding(struct port_list *portlist, int message_type, union parameter *param)
3014 struct message *message;
3016 new_state(EPOINT_STATE_IN_PROCEEDING);
3018 /* own proceeding tone */
3021 /* connect / disconnect audio */
3022 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3023 if (e_ext.own_proceeding)
3024 message->param.channel = CHANNEL_STATE_HOLD;
3026 message->param.channel = CHANNEL_STATE_CONNECT;
3027 message_put(message);
3029 // UCPY(e_call_tone, "proceeding");
3032 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3033 message_put(message);
3034 logmessage(message);
3036 set_tone(portlist, "proceeding");
3039 /* call MESSAGE_ALERTING */
3040 void EndpointAppPBX::call_alerting(struct port_list *portlist, int message_type, union parameter *param)
3042 struct message *message;
3044 new_state(EPOINT_STATE_IN_ALERTING);
3046 /* own alerting tone */
3049 /* connect / disconnect audio */
3050 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3051 if (e_ext.own_alerting)
3052 message->param.channel = CHANNEL_STATE_HOLD;
3054 message->param.channel = CHANNEL_STATE_CONNECT;
3055 message_put(message);
3059 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
3060 message_put(message);
3061 logmessage(message);
3063 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3065 set_tone(portlist, "ringing");
3068 if (e_ext.number[0])
3069 set_tone(portlist, "ringpbx");
3071 set_tone(portlist, "ringing");
3074 /* call MESSAGE_CONNECT */
3075 void EndpointAppPBX::call_connect(struct port_list *portlist, int message_type, union parameter *param)
3077 struct message *message;
3078 struct interface *interface;
3080 new_state(EPOINT_STATE_CONNECT);
3081 // UCPY(e_call_tone, "");
3082 if (e_ext.number[0])
3083 e_dtmf = 1; /* allow dtmf */
3085 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
3088 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3089 memcpy(&message->param, param, sizeof(union parameter));
3090 /* screen incoming caller id */
3091 interface = interface_first;
3094 if (!strcmp(e_connectinfo.interface, interface->name))
3098 interface = interface->next;
3101 screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
3102 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(e_connectinfo));
3104 /* screen clip if prefix is required */
3105 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3107 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3108 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
3109 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3112 /* use internal caller id */
3113 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3115 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
3116 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3119 /* handle restricted caller ids */
3120 apply_callerid_restriction(e_ext.anon_ignore, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
3121 /* display callerid if desired for extension */
3122 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.extension, message->param.connectinfo.name));
3124 /* use conp, if enabld */
3126 message->param.connectinfo.name[0] = '\0';
3129 message_put(message);
3130 logmessage(message);
3132 set_tone(portlist, NULL);
3134 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3135 message->param.channel = CHANNEL_STATE_CONNECT;
3136 message_put(message);
3140 /* call MESSAGE_DISCONNECT MESSAGE_RELEASE */
3141 void EndpointAppPBX::call_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
3144 struct message *message;
3147 /* be sure that we are active */
3149 e_tx_state = NOTIFY_STATE_ACTIVE;
3151 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3152 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3154 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
3156 /* set time for power dialing */
3157 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3160 /* set redial tone */
3161 if (ea_endpoint->ep_portlist)
3165 set_tone(ea_endpoint->ep_portlist, "redial");
3166 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') redialing in %d seconds\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (int)e_powerdelay);
3167 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3168 if (e_state==EPOINT_STATE_IN_OVERLAP)
3170 new_state(EPOINT_STATE_IN_PROCEEDING);
3173 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3174 message_put(message);
3175 logmessage(message);
3177 /* caused the error, that the first knock sound was not there */
3178 /* set_tone(portlist, "proceeding"); */
3180 /* send display of powerdialing */
3181 if (e_ext.display_dialing)
3185 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3187 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3189 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3190 message_put(message);
3191 logmessage(message);
3192 portlist = portlist->next;
3201 if ((e_state!=EPOINT_STATE_CONNECT
3202 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3203 && e_state!=EPOINT_STATE_IN_OVERLAP
3204 && e_state!=EPOINT_STATE_IN_PROCEEDING
3205 && e_state!=EPOINT_STATE_IN_ALERTING)
3206 || !ea_endpoint->ep_portlist) /* or no port */
3208 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3209 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, call, port */
3210 return; /* must exit here */
3215 e_call_cause = param->disconnectinfo.cause;
3216 e_call_location = param->disconnectinfo.location;
3219 /* on release we need the audio again! */
3220 if (message_type == MESSAGE_RELEASE)
3223 ea_endpoint->ep_call_id = 0;
3225 /* disconnect and select tone */
3226 new_state(EPOINT_STATE_OUT_DISCONNECT);
3227 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3228 /* if own_cause, we must release the call */
3229 if (e_ext.own_cause /* own cause */
3230 || !e_call_pattern) /* no patterns */
3232 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);
3233 if (message_type != MESSAGE_RELEASE)
3234 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
3236 } else /* else we enable audio */
3238 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3239 message->param.channel = CHANNEL_STATE_CONNECT;
3240 message_put(message);
3242 /* send disconnect message */
3243 SCPY(e_tone, cause);
3246 set_tone(portlist, cause);
3247 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3248 portlist = portlist->next;
3252 /* call MESSAGE_SETUP */
3253 void EndpointAppPBX::call_setup(struct port_list *portlist, int message_type, union parameter *param)
3255 struct message *message;
3256 struct interface *interface;
3258 /* if we already in setup state, we just update the dialing with new digits */
3259 if (e_state == EPOINT_STATE_OUT_SETUP
3260 || e_state == EPOINT_STATE_OUT_OVERLAP)
3262 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3263 /* if digits changed, what we have already dialed */
3264 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3266 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);
3267 /* release all ports */
3268 while((portlist = ea_endpoint->ep_portlist))
3270 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3271 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3272 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3273 message_put(message);
3274 logmessage(message);
3275 ea_endpoint->free_portlist(portlist);
3278 /* disconnect audio */
3279 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3280 message->param.channel = CHANNEL_STATE_HOLD;
3281 message_put(message);
3283 /* get dialing info */
3284 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3285 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3286 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3287 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3288 new_state(EPOINT_STATE_OUT_OVERLAP);
3291 e_redial = now_d + 1; /* set redial one second in the future */
3294 /* if we have a pending redial, so we just adjust the dialing number */
3297 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) redial in progress, so we update the dialing number to %s.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.id);
3298 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3301 if (!ea_endpoint->ep_portlist)
3303 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3305 if (ea_endpoint->ep_portlist->next)
3307 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3309 if (e_state == EPOINT_STATE_OUT_SETUP)
3312 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.id);
3313 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3317 /* get what we have not dialed yet */
3318 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have already dialed '%s', we received '%s', what's left '%s'.\n", ea_endpoint->ep_serial, e_dialinginfo.id, param->setup.dialinginfo.id, param->setup.dialinginfo.id+strlen(e_dialinginfo.id));
3319 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3320 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3321 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3322 message_put(message);
3323 logmessage(message);
3325 /* always store what we have dialed or queued */
3326 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3330 if (e_state != EPOINT_STATE_IDLE)
3332 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3335 /* if an internal extension is dialed, copy that number */
3336 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3337 SCPY(e_ext.number, param->setup.dialinginfo.id);
3338 /* if an internal extension is dialed, get extension's info about caller */
3339 if (e_ext.number[0])
3341 if (!read_extension(&e_ext, e_ext.number))
3343 e_ext.number[0] = '\0';
3344 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3348 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3349 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3350 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3351 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3353 /* screen incoming caller id */
3354 interface = interface_first;
3357 if (!strcmp(e_callerinfo.interface, interface->name))
3361 interface = interface->next;
3364 screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
3366 /* process (voice over) data calls */
3367 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3369 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3370 memset(&e_capainfo, 0, sizeof(e_capainfo));
3371 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3372 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3373 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3376 new_state(EPOINT_STATE_OUT_SETUP);
3377 /* call special setup routine */
3381 /* call MESSAGE_mISDNSIGNAL */
3382 void EndpointAppPBX::call_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3384 struct message *message;
3388 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3389 memcpy(&message->param, param, sizeof(union parameter));
3390 message_put(message);
3391 portlist = portlist->next;
3395 /* call MESSAGE_NOTIFY */
3396 void EndpointAppPBX::call_notify(struct port_list *portlist, int message_type, union parameter *param)
3398 struct message *message;
3401 if (param->notifyinfo.notify)
3403 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3404 // /* if notification was generated locally, we turn hold music on/off */
3405 // if (param->notifyinfo.local)
3406 // 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)
3411 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3415 set_tone(portlist, "");
3416 portlist = portlist->next;
3418 portlist = ea_endpoint->ep_portlist;
3423 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3427 set_tone(portlist, "hold");
3428 portlist = portlist->next;
3430 portlist = ea_endpoint->ep_portlist;
3435 /* save new state */
3436 e_tx_state = new_state;
3439 /* notify port(s) about it */
3442 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3443 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3444 /* handle restricted caller ids */
3445 apply_callerid_restriction(e_ext.anon_ignore, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3446 /* display callerid if desired for extension */
3447 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.extension, NULL));
3448 message_put(message);
3449 logmessage(message);
3450 portlist = portlist->next;
3454 /* call sends messages to the endpoint
3456 void EndpointAppPBX::ea_message_call(unsigned long call_id, int message_type, union parameter *param)
3458 struct port_list *portlist;
3459 struct message *message;
3463 PERROR("EPOINT(%d) error: call == NULL.\n", ea_endpoint->ep_serial);
3467 portlist = ea_endpoint->ep_portlist;
3469 /* send MESSAGE_DATA to port */
3470 if (message_type == MESSAGE_DATA)
3472 if (call_id == ea_endpoint->ep_call_id) // still linked with call
3474 /* skip if no port relation */
3477 /* skip if more than one port relation */
3480 /* forward audio data to port */
3481 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3486 // PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active call (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
3487 switch(message_type)
3489 /* CALL SENDS CRYPT message */
3491 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
3492 call_crypt(portlist, message_type, param);
3495 /* CALL sends INFORMATION message */
3496 case MESSAGE_INFORMATION:
3497 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received more digits: '%s'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->information.id);
3498 call_information(portlist, message_type, param);
3501 /* CALL sends FACILITY message */
3502 case MESSAGE_FACILITY:
3503 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received facility\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3504 call_facility(portlist, message_type, param);
3507 /* CALL sends OVERLAP message */
3508 case MESSAGE_OVERLAP:
3509 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received 'more info available'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3510 if (e_state!=EPOINT_STATE_IN_SETUP
3511 && e_state!=EPOINT_STATE_IN_OVERLAP)
3513 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3516 call_overlap(portlist, message_type, param);
3519 /* CALL sends PROCEEDING message */
3520 case MESSAGE_PROCEEDING:
3521 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s (caller id '%s') received proceeding\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3522 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3524 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3527 call_proceeding(portlist, message_type, param);
3530 /* CALL sends ALERTING message */
3531 case MESSAGE_ALERTING:
3532 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received alerting\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3533 if (e_state!=EPOINT_STATE_IN_OVERLAP
3534 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3536 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3539 call_alerting(portlist, message_type, param);
3542 /* CALL sends CONNECT message */
3543 case MESSAGE_CONNECT:
3544 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received connect\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3545 if (e_state!=EPOINT_STATE_IN_OVERLAP
3546 && e_state!=EPOINT_STATE_IN_PROCEEDING
3547 && e_state!=EPOINT_STATE_IN_ALERTING)
3549 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3552 call_connect(portlist, message_type, param);
3555 /* CALL sends DISCONNECT/RELEASE message */
3556 case MESSAGE_DISCONNECT: /* call disconnect */
3557 case MESSAGE_RELEASE: /* call releases */
3558 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received %s with cause %d location %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (message_type==MESSAGE_DISCONNECT)?"disconnect":"release", param->disconnectinfo.cause, param->disconnectinfo.location);
3559 call_disconnect_release(portlist, message_type, param);
3562 /* CALL sends SETUP message */
3564 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.extension, param->setup.callerinfo.id, param->setup.dialinginfo.id, param->setup.dialinginfo.itype);
3565 call_setup(portlist, message_type, param);
3569 /* CALL sends special mISDNSIGNAL message */
3570 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3571 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received mISDNsignal message.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3572 call_mISDNsignal(portlist, message_type, param);
3575 /* CALL has pattern available */
3576 case MESSAGE_PATTERN: /* indicating pattern available */
3577 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern availability.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3578 if (!e_call_pattern)
3580 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3585 set_tone(portlist, NULL);
3586 portlist = portlist->next;
3588 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3589 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3590 message->param.channel = CHANNEL_STATE_CONNECT;
3591 message_put(message);
3592 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3593 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_REMOTE_AUDIO);
3594 // message->param.channel = CHANNEL_STATE_CONNECT;
3595 // message_put(message);
3596 // patterns are available, remote already connected audio
3600 /* CALL has no pattern available */
3601 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3602 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern NOT available.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3605 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3607 /* disconnect our audio tx and rx */
3608 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3609 message->param.channel = CHANNEL_STATE_HOLD;
3610 message_put(message);
3615 /* CALL (dunno at the moment) */
3616 case MESSAGE_REMOTE_AUDIO:
3617 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received audio remote request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3618 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3619 message->param.channel = param->channel;
3620 message_put(message);
3624 /* CALL sends a notify message */
3625 case MESSAGE_NOTIFY:
3626 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3627 call_notify(portlist, message_type, param);
3631 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: #%d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message);
3636 /* pick_call will connect the first incoming call found. the endpoint
3637 * will receivce a MESSAGE_CONNECT.
3639 int match_list(char *list, char *item)
3641 char *end, *next = NULL;
3643 /* no list make matching */
3649 /* eliminate white spaces */
3650 while (*list <= ' ')
3657 /* if end of list is reached, we return */
3658 if (list[0] == '\0')
3660 /* if we have more than one entry (left) */
3661 if ((end = strchr(list, ',')))
3664 next = end = strchr(list, '\0');
3665 while (*(end-1) <= ' ')
3667 /* if string part matches item */
3668 if (!strncmp(list, item, end-list))
3674 void EndpointAppPBX::pick_call(char *extensions)
3676 struct message *message;
3677 struct port_list *portlist;
3679 class EndpointAppPBX *eapp, *found;
3681 class CallPBX *callpbx;
3682 struct call_relation *relation;
3685 /* find an endpoint that is ringing internally or vbox with higher priority */
3688 eapp = apppbx_first;
3691 if (eapp!=this && ea_endpoint->ep_portlist)
3693 portlist = eapp->ea_endpoint->ep_portlist;
3696 if ((port = find_port_id(portlist->port_id)))
3698 if (port->p_type == PORT_TYPE_VBOX_OUT)
3700 if (match_list(extensions, eapp->e_ext.number))
3707 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3708 && port->p_state==PORT_STATE_OUT_ALERTING)
3709 if (match_list(extensions, eapp->e_ext.number))
3714 portlist = portlist->next;
3722 /* if no endpoint found */
3725 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);
3727 set_tone(ea_endpoint->ep_portlist, "cause_10");
3728 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3729 new_state(EPOINT_STATE_OUT_DISCONNECT);
3734 if (ea_endpoint->ep_call_id)
3736 PERROR("EPOINT(%d) we already have a call. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3739 if (!eapp->ea_endpoint->ep_call_id)
3741 PERROR("EPOINT(%d) ringing endpoint has no call.\n", ea_endpoint->ep_serial);
3744 call = find_call_id(eapp->ea_endpoint->ep_call_id);
3747 PERROR("EPOINT(%d) ringing endpoint's call not found.\n", ea_endpoint->ep_serial);
3750 if (callpbx->c_type != CALL_TYPE_PBX)
3752 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's call is not a PBX call, so we must reject.\n", ea_endpoint->ep_serial);
3755 callpbx = (class CallPBX *)call;
3756 relation = callpbx->c_relation;
3759 PERROR("EPOINT(%d) ringing endpoint's call has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3762 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3764 relation = relation->next;
3767 PERROR("EPOINT(%d) ringing endpoint's call has no relation to that call. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3772 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3774 if (options.deb & DEBUG_EPOINT)
3776 class Call *debug_c = call_first;
3777 class Endpoint *debug_e = epoint_first;
3778 class Port *debug_p = port_first;
3780 callpbx_debug(callpbx, "EndpointAppPBX::pick_call(before)");
3782 PDEBUG(DEBUG_EPOINT, "showing all calls:\n");
3785 PDEBUG(DEBUG_EPOINT, "call=%ld\n", debug_c->c_serial);
3786 debug_c = debug_c->next;
3788 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3791 PDEBUG(DEBUG_EPOINT, "ep=%ld, call=%ld\n", debug_e->ep_serial, debug_e->ep_call_id);
3792 debug_e = debug_e->next;
3794 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3797 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3798 debug_p = debug_p->next;
3803 ea_endpoint->ep_call_id = eapp->ea_endpoint->ep_call_id; /* we get the call */
3804 relation->epoint_id = ea_endpoint->ep_serial; /* the call gets us */
3805 eapp->ea_endpoint->ep_call_id = 0; /* the ringing endpoint will get disconnected */
3807 /* connnecting our endpoint */
3808 new_state(EPOINT_STATE_CONNECT);
3810 set_tone(ea_endpoint->ep_portlist, NULL);
3812 /* now we send a release to the ringing endpoint */
3813 message = message_create(ea_endpoint->ep_call_id, eapp->ea_endpoint->ep_serial, CALL_TO_EPOINT, MESSAGE_RELEASE);
3814 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3815 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3816 message_put(message);
3818 /* we send a connect to the call with our caller id */
3819 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CONNECT);
3820 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3821 message->param.connectinfo.present = e_callerinfo.present;
3822 message->param.connectinfo.screen = e_callerinfo.screen;
3823 message->param.connectinfo.itype = e_callerinfo.itype;
3824 message->param.connectinfo.ntype = e_callerinfo.ntype;
3825 message_put(message);
3827 /* we send a connect to our port with the remote callerid */
3828 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3829 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3830 message->param.connectinfo.present = eapp->e_callerinfo.present;
3831 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3832 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3833 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3834 /* handle restricted caller ids */
3835 apply_callerid_restriction(e_ext.anon_ignore, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
3836 /* display callerid if desired for extension */
3837 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.extension, message->param.connectinfo.name));
3838 message_put(message);
3840 /* we send a connect to the audio path (not for vbox) */
3841 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3842 message->param.channel = CHANNEL_STATE_CONNECT;
3843 message_put(message);
3845 /* beeing paranoid, we make call update */
3846 callpbx->c_updatebridge = 1;
3848 if (options.deb & DEBUG_EPOINT)
3850 class Call *debug_c = call_first;
3851 class Endpoint *debug_e = epoint_first;
3852 class Port *debug_p = port_first;
3854 callpbx_debug(callpbx, "EndpointAppPBX::pick_call(after)");
3856 PDEBUG(DEBUG_EPOINT, "showing all calls:\n");
3859 PDEBUG(DEBUG_EPOINT, "call=%ld\n", debug_c->c_serial);
3860 debug_c = debug_c->next;
3862 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3865 PDEBUG(DEBUG_EPOINT, "ep=%ld, call=%ld\n", debug_e->ep_serial, debug_e->ep_call_id);
3866 debug_e = debug_e->next;
3868 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3871 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3872 debug_p = debug_p->next;
3878 /* join calls (look for a call that is on hold (same isdn interface/terminal))
3880 void EndpointAppPBX::join_call(void)
3882 struct message *message;
3883 struct call_relation *our_relation, *other_relation;
3884 struct call_relation **our_relation_pointer, **other_relation_pointer;
3885 class Call *our_call, *other_call;
3886 class CallPBX *our_callpbx, *other_callpbx;
3887 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3888 class Port *our_port, *other_port;
3889 class Pdss1 *our_pdss1, *other_pdss1;
3891 /* are we a candidate to join a call */
3892 our_call = find_call_id(ea_endpoint->ep_call_id);
3895 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our call doesn't exist anymore.\n", ea_endpoint->ep_serial);
3898 if (our_call->c_type != CALL_TYPE_PBX)
3900 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: call is not a pbx call.\n", ea_endpoint->ep_serial);
3903 our_callpbx = (class CallPBX *)our_call;
3904 if (!ea_endpoint->ep_portlist)
3906 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3909 if (!e_ext.number[0])
3911 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3914 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3917 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3920 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3922 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3925 our_pdss1 = (class Pdss1 *)our_port;
3927 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3928 other_eapp = apppbx_first;
3931 if (other_eapp == this)
3933 other_eapp = other_eapp->next;
3936 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint candiate: (ep%d) terminal='%s' port=%s call=%d.\n", ea_endpoint->ep_serial, other_eapp->ea_endpoint->ep_serial, other_eapp->e_ext.number, (other_eapp->ea_endpoint->ep_portlist)?"YES":"NO", other_eapp->ea_endpoint->ep_call_id);
3937 if (other_eapp->e_ext.number[0] /* has terminal */
3938 && other_eapp->ea_endpoint->ep_portlist /* has port */
3939 && other_eapp->ea_endpoint->ep_call_id) /* has call */
3941 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3942 if (other_port) /* port still exists */
3944 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3945 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3947 other_pdss1 = (class Pdss1 *)other_port;
3948 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);
3949 if (other_pdss1->p_m_hold /* port is on hold */
3950 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3951 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3955 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3959 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3962 other_eapp = other_eapp->next;
3966 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3969 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3971 /* if we have the same call */
3972 if (other_eapp->ea_endpoint->ep_call_id == ea_endpoint->ep_call_id)
3974 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same call.\n", ea_endpoint->ep_serial);
3977 other_call = find_call_id(other_eapp->ea_endpoint->ep_call_id);
3980 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other call doesn't exist anymore.\n", ea_endpoint->ep_serial);
3983 if (other_call->c_type != CALL_TYPE_PBX)
3985 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other call is not a pbx call.\n", ea_endpoint->ep_serial);
3988 other_callpbx = (class CallPBX *)other_call;
3989 if (our_callpbx->c_partyline && other_callpbx->c_partyline)
3991 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both calls are partylines.\n", ea_endpoint->ep_serial);
3995 /* remove relation to endpoint for call on hold */
3996 other_relation = other_callpbx->c_relation;
3997 other_relation_pointer = &other_callpbx->c_relation;
3998 while(other_relation)
4000 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
4002 /* detach other endpoint on hold */
4003 *other_relation_pointer = other_relation->next;
4004 FREE(other_relation, sizeof(struct call_relation));
4006 other_relation = *other_relation_pointer;
4007 other_eapp->ea_endpoint->ep_call_id = NULL;
4011 /* change call/hold pointer of endpoint to the new call */
4012 temp_epoint = find_epoint_id(other_relation->epoint_id);
4015 if (temp_epoint->ep_call_id == other_call->c_serial)
4016 temp_epoint->ep_call_id = our_call->c_serial;
4019 other_relation_pointer = &other_relation->next;
4020 other_relation = other_relation->next;
4022 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on call relinked (to our call).\n", ea_endpoint->ep_serial);
4024 /* join call relations */
4025 our_relation = our_callpbx->c_relation;
4026 our_relation_pointer = &our_callpbx->c_relation;
4029 our_relation_pointer = &our_relation->next;
4030 our_relation = our_relation->next;
4032 *our_relation_pointer = other_callpbx->c_relation;
4033 other_callpbx->c_relation = NULL;
4034 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
4036 /* release endpoint on hold */
4037 message = message_create(other_callpbx->c_serial, other_eapp->ea_endpoint->ep_serial, CALL_TO_EPOINT, MESSAGE_RELEASE);
4038 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
4039 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
4040 message_put(message);
4042 /* if we are not a partyline, we get partyline state from other call */
4043 our_callpbx->c_partyline += other_callpbx->c_partyline;
4045 /* remove empty call */
4047 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-call completely removed!\n");
4049 /* mixer must update */
4050 our_callpbx->c_updatebridge = 1; /* update mixer flag */
4052 /* we send a retrieve to that endpoint */
4053 // mixer will update the hold-state of the call and send it to the endpoints is changes
4057 /* check if we have an external call
4058 * this is used to check for encryption ability
4060 int EndpointAppPBX::check_external(char **errstr, class Port **port)
4062 struct call_relation *relation;
4064 class CallPBX *callpbx;
4065 class Endpoint *epoint;
4067 /* some paranoia check */
4068 if (!ea_endpoint->ep_portlist)
4070 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4071 *errstr = "No Call";
4074 if (!e_ext.number[0])
4076 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4077 *errstr = "No Call";
4081 /* check if we have a call with 2 parties */
4082 call = find_call_id(ea_endpoint->ep_call_id);
4085 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no call.\n", ea_endpoint->ep_serial);
4086 *errstr = "No Call";
4089 if (call->c_type != CALL_TYPE_PBX)
4091 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call is nto a pbx call.\n", ea_endpoint->ep_serial);
4092 *errstr = "No PBX Call";
4095 callpbx = (class CallPBX *)call;
4096 relation = callpbx->c_relation;
4099 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no relation.\n", ea_endpoint->ep_serial);
4100 *errstr = "No Call";
4103 if (!relation->next)
4105 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no 2nd relation.\n", ea_endpoint->ep_serial);
4106 *errstr = "No Call";
4109 if (relation->next->next)
4111 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has more than two relations.\n", ea_endpoint->ep_serial);
4112 *errstr = "Err: Conference";
4115 if (relation->epoint_id == ea_endpoint->ep_serial)
4117 relation = relation->next;
4118 if (relation->epoint_id == ea_endpoint->ep_serial)
4120 PERROR("EPOINT(%d) SOFTWARE ERROR: both call relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4121 *errstr = "Software Error";
4126 /* check remote port for external call */
4127 epoint = find_epoint_id(relation->epoint_id);
4130 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4131 *errstr = "No Call";
4134 if (!epoint->ep_portlist)
4136 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4137 *errstr = "No Call";
4140 *port = find_port_id(epoint->ep_portlist->port_id);
4143 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4144 *errstr = "No Call";
4147 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4149 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4150 *errstr = "No Ext Call";
4153 if ((*port)->p_state != PORT_STATE_CONNECT)
4155 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4156 *errstr = "No Ext Connect";
4162 void EndpointAppPBX::logmessage(struct message *message)
4164 char *logtext = "unknown";
4167 if (message->flow != EPOINT_TO_PORT)
4169 PERROR("EPOINT(%d) message not of correct flow type-\n", ea_endpoint->ep_serial);
4173 switch(message->type)
4176 trace_header("SETUP", DIRECTION_OUT);
4177 if (message->param.setup.callerinfo.extension[0])
4178 add_trace("extension", NULL, "%s", message->param.setup.callerinfo.extension);
4179 add_trace("caller id", "number", "%s", numberrize_callerinfo(message->param.setup.callerinfo.id, message->param.setup.callerinfo.ntype));
4180 if (message->param.setup.callerinfo.present == INFO_PRESENT_RESTRICTED)
4181 add_trace("caller id", "present", "restricted");
4182 if (message->param.setup.redirinfo.id[0])
4184 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(message->param.setup.redirinfo.id, message->param.setup.redirinfo.ntype));
4185 if (message->param.setup.redirinfo.present == INFO_PRESENT_RESTRICTED)
4186 add_trace("redir'ing", "present", "restricted");
4188 if (message->param.setup.dialinginfo.id[0])
4189 add_trace("dialing", NULL, "%s", message->param.setup.dialinginfo.id);
4193 case MESSAGE_OVERLAP:
4194 trace_header("SETUP ACKNOWLEDGE", DIRECTION_OUT);
4198 case MESSAGE_PROCEEDING:
4199 trace_header("PROCEEDING", DIRECTION_OUT);
4203 case MESSAGE_ALERTING:
4204 trace_header("ALERTING", DIRECTION_OUT);
4208 case MESSAGE_CONNECT:
4209 trace_header("CONNECT", DIRECTION_OUT);
4210 if (message->param.connectinfo.extension[0])
4211 add_trace("extension", NULL, "%s", message->param.connectinfo.extension);
4212 add_trace("connect id", "number", "%s", numberrize_callerinfo(message->param.connectinfo.id, message->param.connectinfo.ntype));
4213 if (message->param.connectinfo.present == INFO_PRESENT_RESTRICTED)
4214 add_trace("connect id", "present", "restricted");
4218 case MESSAGE_DISCONNECT:
4219 trace_header("DISCONNECT", DIRECTION_OUT);
4220 add_trace("cause", "value", "%d", message->param.disconnectinfo.cause);
4221 add_trace("cause", "location", "%d", message->param.disconnectinfo.location);
4225 case MESSAGE_RELEASE:
4226 trace_header("RELEASE", DIRECTION_OUT);
4227 add_trace("cause", "value", "%d", message->param.disconnectinfo.cause);
4228 add_trace("cause", "location", "%d", message->param.disconnectinfo.location);
4232 case MESSAGE_NOTIFY:
4233 switch(message->param.notifyinfo.notify)
4239 logtext = "USER_SUSPENDED";
4242 logtext = "BEARER_SERVICE_CHANGED";
4245 logtext = "USER_RESUMED";
4248 logtext = "CONFERENCE_ESTABLISHED";
4251 logtext = "CONFERENCE_DISCONNECTED";
4254 logtext = "OTHER_PARTY_ADDED";
4257 logtext = "ISOLATED";
4260 logtext = "REATTACHED";
4263 logtext = "OTHER_PARTY_ISOLATED";
4266 logtext = "OTHER_PARTY_REATTACHED";
4269 logtext = "OTHER_PARTY_SPLIT";
4272 logtext = "OTHER_PARTY_DISCONNECTED";
4275 logtext = "CONFERENCE_FLOATING";
4278 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4281 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4284 logtext = "CALL_IS_A_WAITING_CALL";
4287 logtext = "DIVERSION_ACTIVATED";
4290 logtext = "RESERVED_CT_1";
4293 logtext = "RESERVED_CT_2";
4296 logtext = "REVERSE_CHARGING";
4299 logtext = "REMOTE_HOLD";
4302 logtext = "REMOTE_RETRIEVAL";
4305 logtext = "CALL_IS_DIVERTING";
4308 SPRINT(buffer, "%d", message->param.notifyinfo.notify - 0x80);
4312 trace_header("NOTIFY", DIRECTION_OUT);
4313 if (message->param.notifyinfo.notify)
4314 add_trace("indicator", NULL, "%s", logtext);
4315 if (message->param.notifyinfo.id[0])
4317 add_trace("redir'on", "number", "%s", numberrize_callerinfo(message->param.notifyinfo.id, message->param.notifyinfo.ntype));
4318 if (message->param.notifyinfo.present == INFO_PRESENT_RESTRICTED)
4319 add_trace("redir'on", "present", "restricted");
4321 if (message->param.notifyinfo.display[0])
4322 add_trace("display", NULL, "%s", message->param.notifyinfo.display);
4326 case MESSAGE_INFORMATION:
4327 trace_header("INFORMATION", DIRECTION_OUT);
4328 add_trace("dialing", NULL, "%s", message->param.information.id);
4332 case MESSAGE_FACILITY:
4333 trace_header("FACILITY", DIRECTION_OUT);
4338 trace_header("TONE", DIRECTION_OUT);
4339 if (message->param.tone.name[0])
4341 add_trace("directory", NULL, "%s", message->param.tone.dir[0]?message->param.tone.dir:"default");
4342 add_trace("name", NULL, "%s", message->param.tone.name);
4344 add_trace("off", NULL, NULL);
4349 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message->type);
4353 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4355 struct message *message;
4359 if (!portlist->port_id)
4362 if (!e_connectedmode)
4364 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4365 message->param.disconnectinfo.cause = cause;
4366 message->param.disconnectinfo.location = location;
4368 SCPY(message->param.disconnectinfo.display, display);
4370 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4373 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4375 SCPY(message->param.notifyinfo.display, display);
4377 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4379 message_put(message);
4380 logmessage(message);