1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 #include <sys/types.h>
23 class EndpointAppPBX *apppbx_first = NULL;
26 * EndpointAppPBX constructor
28 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint) : EndpointApp(epoint)
30 class EndpointAppPBX **apppointer;
32 /* add application to chain */
34 apppointer = &apppbx_first;
36 apppointer = &((*apppointer)->next);
40 memset(&e_ext, 0, sizeof(struct extension));
41 e_ext.rights = 4; /* international */
42 e_ext.rxvol = e_ext.txvol = 256;
43 e_state = EPOINT_STATE_IDLE;
44 e_ext.number[0] = '\0';
45 e_extension_interface[0] = '\0';
46 memset(&e_callerinfo, 0, sizeof(struct caller_info));
47 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
48 memset(&e_connectinfo, 0, sizeof(struct connect_info));
49 memset(&e_redirinfo, 0, sizeof(struct redir_info));
50 memset(&e_capainfo, 0, sizeof(struct capa_info));
53 e_ruleset = ruleset_main;
55 e_rule = e_ruleset->rule_first;
60 e_match_to_action = NULL;
62 e_extdialing = e_dialinginfo.id;
66 // e_join_tone[0] = e_hold_tone[0] = '\0';
67 e_join_pattern /*= e_hold_pattern*/ = 0;
70 e_adminid = 0; // will be set, if call was initiated via admin socket
75 e_cbdialing[0] = '\0';
78 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
85 e_password_timeout = 0;
86 e_multipoint_cause = CAUSE_NOUSER;
87 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
88 e_dialing_queue[0] = '\0';
90 e_crypt_state = CM_ST_NULL;
91 e_crypt_keyengine_busy = 0;
92 e_crypt_info[0] = '\0';
95 e_tx_state = NOTIFY_STATE_ACTIVE;
96 e_rx_state = NOTIFY_STATE_ACTIVE;
97 e_join_cause = e_join_location = 0;
98 /*********************************
99 *********************************
100 ********* ATTENTION *************
101 *********************************
102 *********************************/
103 /* if you add new values, that must be initialized, also check if they must
104 * be initialized when doing callback
110 * EpointAppPBX destructor
112 EndpointAppPBX::~EndpointAppPBX(void)
114 class EndpointAppPBX *temp, **tempp;
118 tempp = &apppbx_first;
128 FATAL("Endpoint not in endpoint's list.\n");
135 * trace header for application
137 void EndpointAppPBX::trace_header(char *name, int direction)
141 char msgtext[sizeof(_trace.name)];
145 /* init trace with given values */
148 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype),
152 ea_endpoint->ep_serial,
159 /* set new endpoint state
161 void EndpointAppPBX::new_state(int state)
164 if (e_state != state)
166 trace_header("NEW STATE", DIRECTION_NONE);
167 add_trace("state", "old", "%s", state_name[e_state]);
168 add_trace("state", "new", "%s", state_name[state]);
177 * out==0: incomming caller id, out==1: outgoing caller id
179 void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
182 struct interface_msn *ifmsn;
183 struct interface_screen *ifscreen;
186 /* screen incoming caller id */
189 /* check for MSN numbers, use first MSN if no match */
191 ifmsn = interface->ifmsn;
196 if (!strcmp(ifmsn->msn, id))
204 trace_header("SCREEN (found in list)", DIRECTION_IN);
205 add_trace("msn", NULL, "%s", id);
208 if (!ifmsn && msn1) // not in list, first msn given
210 trace_header("SCREEN (not found in list)", DIRECTION_IN);
211 add_trace("msn", "given", "%s", id);
212 add_trace("msn", "used", "%s", msn1);
214 UNCPY(id, msn1, idsize);
219 /* check screen list */
221 ifscreen = interface->ifscreen_out;
223 ifscreen = interface->ifscreen_in;
226 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
227 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
229 if (strchr(ifscreen->match,'%'))
231 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
235 if (!strcmp(ifscreen->match, id))
239 ifscreen = ifscreen->next;
241 if (ifscreen) // match
243 trace_header("SCREEN (found in list)", out?DIRECTION_OUT:DIRECTION_IN);
246 case INFO_NTYPE_UNKNOWN:
247 add_trace("given", "type", "unknown");
249 case INFO_NTYPE_SUBSCRIBER:
250 add_trace("given", "type", "subscriber");
252 case INFO_NTYPE_NATIONAL:
253 add_trace("given", "type", "national");
255 case INFO_NTYPE_INTERNATIONAL:
256 add_trace("given", "type", "international");
261 case INFO_PRESENT_ALLOWED:
262 add_trace("given", "present", "allowed");
264 case INFO_PRESENT_RESTRICTED:
265 add_trace("given", "present", "restricted");
267 case INFO_PRESENT_NOTAVAIL:
268 add_trace("given", "present", "not available");
271 add_trace("given", "id", "%s", id[0]?id:"<empty>");
272 if (ifscreen->result_type != -1)
274 *type = ifscreen->result_type;
277 case INFO_NTYPE_UNKNOWN:
278 add_trace("used", "type", "unknown");
280 case INFO_NTYPE_SUBSCRIBER:
281 add_trace("used", "type", "subscriber");
283 case INFO_NTYPE_NATIONAL:
284 add_trace("used", "type", "national");
286 case INFO_NTYPE_INTERNATIONAL:
287 add_trace("used", "type", "international");
291 if (ifscreen->result_present != -1)
293 *present = ifscreen->result_present;
296 case INFO_PRESENT_ALLOWED:
297 add_trace("used", "present", "allowed");
299 case INFO_PRESENT_RESTRICTED:
300 add_trace("used", "present", "restricted");
302 case INFO_PRESENT_NOTAVAIL:
303 add_trace("used", "present", "not available");
307 if (strchr(ifscreen->match,'%'))
309 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
310 UNCPY(id, ifscreen->result, idsize);
312 if (strchr(ifscreen->result,'%'))
314 *strchr(ifscreen->result,'%') = '\0';
315 UNCAT(id, suffix, idsize);
320 UNCPY(id, ifscreen->result, idsize);
323 add_trace("used", "id", "%s", id[0]?id:"<empty>");
328 /* release join and port (as specified)
330 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
332 struct port_list *portlist;
333 struct message *message;
336 /* message to test call */
337 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
339 /* if a release is pending */
340 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
342 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
343 if (ea_endpoint->ep_join_id)
345 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
346 message->param.disconnectinfo.cause = joincause;
347 message->param.disconnectinfo.location = joinlocation;
348 message_put(message);
349 ea_endpoint->ep_join_id = 0;
353 if (release != RELEASE_PORT_JOINONLY)
356 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
361 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
363 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
364 while((portlist = ea_endpoint->ep_portlist))
366 if (portlist->port_id)
368 SPRINT(cause, "cause_%02x", portcause);
369 set_tone(portlist, cause);
370 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
371 message->param.disconnectinfo.cause = portcause;
372 message->param.disconnectinfo.location = portlocation;
373 message_put(message);
374 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
376 ea_endpoint->free_portlist(portlist);
379 /* if callback is enabled, call back with the given caller id */
382 /* reset some stuff */
383 new_state(EPOINT_STATE_IDLE);
384 memset(&e_connectinfo, 0, sizeof(struct connect_info));
385 memset(&e_redirinfo, 0, sizeof(struct redir_info));
386 e_start = e_stop = 0;
387 e_ruleset = ruleset_main;
389 e_rule = e_ruleset->rule_first;
391 e_action_timeout = 0;
393 e_match_to_action = NULL;
395 e_extdialing = e_dialinginfo.id;
402 e_multipoint_cause = CAUSE_NOUSER;
403 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
404 e_dialing_queue[0] = '\0';
406 e_crypt_state = CM_ST_NULL;
407 e_crypt_keyengine_busy = 0;
408 e_crypt_info[0] = '\0';
412 e_tx_state = NOTIFY_STATE_ACTIVE;
413 e_rx_state = NOTIFY_STATE_ACTIVE;
414 e_join_cause = e_join_location = 0;
416 /* the caller info of the callback user */
417 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
418 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
419 /* create dialing by callerinfo */
420 if (e_ext.number[0] && e_extension_interface[0])
422 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
423 /* create callback to the current terminal */
424 SCPY(e_dialinginfo.id, e_ext.number);
425 SCPY(e_dialinginfo.interfaces, e_extension_interface);
426 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
427 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
432 SCPY(e_dialinginfo.id, e_cbto);
435 /* numberrize caller id and use it to dial to the callback */
436 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
438 e_dialinginfo.itype = INFO_ITYPE_ISDN;
439 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
440 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
445 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
446 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
452 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
453 void apply_callerid_restriction(int anon_ignore, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
455 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");
457 /* caller id is not restricted, so we do nothing */
458 if (*present != INFO_PRESENT_RESTRICTED)
461 /* only extensions are restricted */
467 /* if we enabled anonymouse ignore */
471 /* else we remove the caller id */
475 *ntype = INFO_NTYPE_UNKNOWN;
477 // *screen = INFO_SCREEN_USER;
478 // maybe we should not make voip address anonymous
481 // maybe it's no fraud to present extension id
483 // extension[0] = '\0';
488 /* used display message to display callerid as available */
489 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *extension, char *name)
491 static char display[81];
494 char *cid = numberrize_callerinfo(id, ntype);
496 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");
505 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
507 /* internal extension's caller id */
508 if (extension[0] && e_ext.display_int)
511 SCAT(display, extension);
514 if (itype == INFO_ITYPE_VBOX)
515 SCAT(display, "(vbox)");
517 SCAT(display, "(int)");
520 /* external caller id */
521 if (!extension[0] && e_ext.display_ext)
527 if (present == INFO_PRESENT_RESTRICTED)
528 SCAT(display, "anonymous");
530 SCAT(display, "unknown");
537 /* display if callerid is anonymouse but available due anon-ignore */
538 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
541 SCAT(display, "unknown");
544 SCAT(display, " anon");
547 /* display if callerid is anonymouse but available due anon-ignore */
548 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
554 if (present == INFO_PRESENT_RESTRICTED)
555 SCAT(display, "anonymous");
557 SCAT(display, "unknown");
562 SCAT(display, " fake");
566 if (name[0] && e_ext.display_name)
568 if (!display[0] && cid[0])
579 * uses the current state to notify activity
581 void EndpointAppPBX::notify_active(void)
583 struct port_list *portlist = ea_endpoint->ep_portlist;
584 struct message *message;
589 case NOTIFY_STATE_ACTIVE:
590 /* we are already active, so we don't do anything */
593 case NOTIFY_STATE_SUSPEND:
594 notify = INFO_NOTIFY_USER_RESUMED;
597 set_tone(portlist, NULL);
598 portlist = portlist->next;
600 portlist = ea_endpoint->ep_portlist;
603 case NOTIFY_STATE_HOLD:
604 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
607 set_tone(portlist, NULL);
608 portlist = portlist->next;
610 portlist = ea_endpoint->ep_portlist;
613 case NOTIFY_STATE_CONFERENCE:
614 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
617 set_tone(portlist, NULL);
618 portlist = portlist->next;
620 portlist = ea_endpoint->ep_portlist;
624 PERROR("unknown e_tx_state = %d\n", e_tx_state);
630 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
631 message->param.notifyinfo.notify = notify;
632 message_put(message);
633 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
634 portlist = portlist->next;
640 * keypad functions during call. one example to use this is to put a call on hold or start a conference
642 void EndpointAppPBX::keypad_function(char digit)
645 /* we must be in a call, in order to send messages to the call */
646 if (e_ext.number[0] == '\0')
648 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
654 /* join conference */
656 if (ea_endpoint->ep_join_id == 0)
658 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
661 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
667 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
671 /* crypt key-exchange */
673 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
679 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
684 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
689 /* set tone pattern for port */
690 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
692 struct message *message;
697 /* store for suspended processes */
702 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no endpoint to notify tone.\n", ea_endpoint->ep_serial);
706 if (e_join_pattern /* pattern are provided */
707 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
708 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
709 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
710 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
711 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
712 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
713 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
714 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
715 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
716 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
717 && tone[0] && !!strncmp(tone,"crypt_*",6))
719 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
725 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
726 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
727 SCPY(message->param.tone.name, tone);
728 message_put(message);
729 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
735 * hunts an mISDNport that is available for an outgoing call
736 * if no ifname was given, any interface that is not an extension
739 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
741 struct interface *interface;
742 struct interface_port *ifport, *ifport_start;
743 struct select_channel *selchannel;
744 struct mISDNport *mISDNport;
747 interface = interface_first;
749 /* first find the given interface or, if not given, one with no extension */
754 /* check for given interface */
757 if (!strcasecmp(interface->name, ifname))
759 /* found explicit interface */
760 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
761 add_trace("interface", NULL, "%s", ifname);
768 if (!interface->extension)
770 /* found non extension */
771 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
772 add_trace("interface", NULL, "%s", interface->name);
778 interface = interface->next;
782 /* see if interface has ports */
783 if (!interface->ifport)
786 trace_header("CHANNEL SELECTION (interface has no active ports, skipping)", DIRECTION_NONE);
787 add_trace("interface", NULL, "%s", interface->name);
789 interface = interface->next;
793 /* select port by algorithm */
794 ifport_start = interface->ifport;
796 if (interface->hunt == HUNT_ROUNDROBIN)
798 while(ifport_start->next && index<interface->hunt_next)
800 ifport_start = ifport_start->next;
803 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
804 add_trace("port", NULL, "%d", ifport_start->portnum);
805 add_trace("position", NULL, "%d", index);
810 ifport = ifport_start;
813 /* see if port is available */
814 if (!ifport->mISDNport)
816 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
817 add_trace("port", NULL, "%d", ifport->portnum);
818 add_trace("position", NULL, "%d", index);
822 mISDNport = ifport->mISDNport;
824 /* see if port is administratively blocked */
827 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
828 add_trace("port", NULL, "%d", ifport->portnum);
829 add_trace("position", NULL, "%d", index);
834 /* see if link is up on PTP*/
835 if (mISDNport->ptp && !mISDNport->l2link)
837 trace_header("CHANNEL SELECTION (port is ptp with layer 2 down, skipping)", DIRECTION_NONE);
838 add_trace("port", NULL, "%d", ifport->portnum);
839 add_trace("position", NULL, "%d", index);
844 /* check for channel form selection list */
846 selchannel = ifport->out_channel;
849 switch(selchannel->channel)
851 case CHANNEL_FREE: /* free channel */
852 if (mISDNport->b_reserved >= mISDNport->b_num)
853 break; /* all channel in use or reserverd */
856 while(i < mISDNport->b_num)
858 if (mISDNport->b_port[i] == NULL)
860 *channel = i+1+(i>=15);
861 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
862 add_trace("port", NULL, "%d", ifport->portnum);
863 add_trace("position", NULL, "%d", index);
864 add_trace("channel", NULL, "%d", *channel);
872 case CHANNEL_ANY: /* don't ask for channel */
873 if (mISDNport->b_reserved >= mISDNport->b_num)
875 break; /* all channel in use or reserverd */
877 trace_header("CHANNEL SELECTION (using 'any channel')", DIRECTION_NONE);
878 add_trace("port", NULL, "%d", ifport->portnum);
879 add_trace("position", NULL, "%d", index);
881 *channel = CHANNEL_ANY;
884 case CHANNEL_NO: /* call waiting */
885 trace_header("CHANNEL SELECTION (using 'no channel', call-waiting)", DIRECTION_NONE);
886 add_trace("port", NULL, "%d", ifport->portnum);
887 add_trace("position", NULL, "%d", index);
889 *channel = CHANNEL_NO;
893 if (selchannel->channel<1 || selchannel->channel==16)
894 break; /* invalid channels */
895 i = selchannel->channel-1-(selchannel->channel>=17);
896 if (i >= mISDNport->b_num)
897 break; /* channel not in port */
898 if (mISDNport->b_port[i] == NULL)
900 *channel = selchannel->channel;
901 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
902 add_trace("port", NULL, "%d", ifport->portnum);
903 add_trace("position", NULL, "%d", index);
904 add_trace("channel", NULL, "%d", *channel);
911 break; /* found channel */
912 selchannel = selchannel->next;
915 /* if channel was found, return mISDNport and channel */
918 /* setting next port to start next time */
919 if (interface->hunt == HUNT_ROUNDROBIN)
924 interface->hunt_next = index;
930 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
931 add_trace("port", NULL, "%d", ifport->portnum);
932 add_trace("position", NULL, "%d", index);
936 /* go next port, until all ports are checked */
938 ifport = ifport->next;
942 ifport = interface->ifport;
944 if (ifport != ifport_start)
947 return(NULL); /* no port found */
950 /* outgoing setup to port(s)
951 * ports will be created and a setup is sent if everything is ok. otherwhise
952 * the endpoint is destroyed.
954 void EndpointAppPBX::out_setup(void)
956 struct dialing_info dialinginfo;
958 // class pdss1 *pdss1;
959 struct port_list *portlist;
960 struct message *message;
962 int cause = CAUSE_RESSOURCEUNAVAIL;
965 struct mISDNport *mISDNport;
968 class EndpointAppPBX *atemp;
969 // char allowed_ports[256];
971 char ifname[sizeof(e_ext.interfaces)],
973 struct port_settings port_settings;
977 /* create settings for creating port */
978 memset(&port_settings, 0, sizeof(port_settings));
980 SCPY(port_settings.tones_dir, e_ext.tones_dir);
982 SCPY(port_settings.tones_dir, options.tones_dir);
983 port_settings.tout_setup = e_ext.tout_setup;
984 port_settings.tout_dialing = e_ext.tout_dialing;
985 port_settings.tout_proceeding = e_ext.tout_proceeding;
986 port_settings.tout_alerting = e_ext.tout_alerting;
987 port_settings.tout_disconnect = e_ext.tout_disconnect;
988 // port_settings.tout_hold = e_ext.tout_hold;
989 // port_settings.tout_park = e_ext.tout_park;
990 port_settings.no_seconds = e_ext.no_seconds;
992 /* 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 */
994 /* check what dialinginfo.itype we got */
995 switch(e_dialinginfo.itype)
997 /* *********************** call to extension or vbox */
998 case INFO_ITYPE_ISDN_EXTENSION:
999 /* check if we deny incoming calls when we use an extension */
1000 if (e_ext.noknocking)
1002 atemp = apppbx_first;
1006 if (!strcmp(atemp->e_ext.number, e_ext.number))
1008 atemp = atemp->next;
1012 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
1013 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
1014 return; /* must exit here */
1017 /* FALL THROUGH !!!! */
1018 case INFO_ITYPE_VBOX:
1019 /* get dialed extension's info */
1020 // SCPY(exten, e_dialinginfo.id);
1021 // if (strchr(exten, ','))
1022 // *strchr(exten, ',') = '\0';
1023 // if (!read_extension(&e_ext, exten))
1024 if (!read_extension(&e_ext, e_dialinginfo.id))
1026 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1027 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1028 return; /* must exit here */
1031 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
1033 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
1038 /* string from unconditional call forward (cfu) */
1042 /* present to forwarded party */
1043 if (e_ext.anon_ignore && e_callerinfo.id[0])
1045 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1047 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1051 /* string from busy call forward (cfb) */
1055 class EndpointAppPBX *checkapp = apppbx_first;
1058 if (checkapp != this) /* any other endpoint except our own */
1060 if (!strcmp(checkapp->e_ext.number, e_ext.number))
1062 /* present to forwarded party */
1063 if (e_ext.anon_ignore && e_callerinfo.id[0])
1065 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1067 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1071 checkapp = checkapp->next;
1075 /* string from no-response call forward (cfnr) */
1079 /* when cfnr is done, out_setup() will setup the call */
1082 /* present to forwarded party */
1083 if (e_ext.anon_ignore && e_callerinfo.id[0])
1085 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1089 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1091 e_cfnr_release = now + e_ext.cfnr_delay;
1092 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
1093 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);
1097 /* call to all internal interfaces */
1098 p = e_ext.interfaces;
1099 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1103 while(*p!=',' && *p!='\0')
1105 SCCAT(ifname, *p++);
1108 /* found interface */
1109 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
1110 /* hunt for mISDNport and create Port */
1111 mISDNport = hunt_port(ifname, &channel);
1114 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
1115 add_trace("interface", NULL, "%s", ifname);
1119 /* creating INTERNAL port */
1120 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1121 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force);
1123 FATAL("No memory for DSS1 Port instance\n");
1124 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1125 memset(&dialinginfo, 0, sizeof(dialinginfo));
1126 SCPY(dialinginfo.id, e_dialinginfo.id);
1127 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1128 dialinginfo.ntype = e_dialinginfo.ntype;
1129 /* create port_list relation */
1130 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1133 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1135 goto check_anycall_intern;
1137 /* directory.list */
1138 if (e_callerinfo.id[0] && (e_ext.centrex || e_ext.display_name))
1140 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1142 SCPY(e_callerinfo.name, dirname);
1144 // dss1 = (class Pdss1 *)port;
1146 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1147 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1148 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1149 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1150 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1151 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1152 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1153 //terminal if (e_dialinginfo.id)
1154 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1155 /* handle restricted caller ids */
1156 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);
1157 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);
1158 /* display callerid if desired for extension */
1159 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));
1160 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1161 /* use cnip, if enabld */
1163 message->param.setup.callerinfo.name[0] = '\0';
1164 /* screen clip if prefix is required */
1165 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1167 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1168 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
1169 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1171 /* use internal caller id */
1172 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1174 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1175 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1177 message_put(message);
1178 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1182 /* string from parallel call forward (cfp) */
1186 if (e_ext.anon_ignore && e_callerinfo.id[0])
1188 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1192 vbox_only: /* entry point for answering machine only */
1193 cfu_only: /* entry point for cfu */
1194 cfb_only: /* entry point for cfb */
1195 cfnr_only: /* entry point for cfnr */
1196 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1201 /* only if vbox should be dialed, and terminal is given */
1202 if (!strcmp(p, "vbox") && e_ext.number[0])
1204 /* go to the end of p */
1207 /* answering vbox call */
1208 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1210 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1211 FATAL("No memory for VBOX Port instance\n");
1212 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1213 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1217 while(*p!=',' && *p!='\0')
1222 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1223 /* hunt for mISDNport and create Port */
1224 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1227 /* creating EXTERNAL port*/
1228 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1229 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)))
1230 FATAL("No memory for DSS1 Port instance\n");
1231 earlyb = mISDNport->earlyb;
1235 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1236 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1242 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1243 goto check_anycall_intern;
1245 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1246 memset(&dialinginfo, 0, sizeof(dialinginfo));
1247 SCPY(dialinginfo.id, cfp);
1248 dialinginfo.itype = INFO_ITYPE_ISDN;
1249 dialinginfo.ntype = e_dialinginfo.ntype;
1250 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1253 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1255 goto check_anycall_intern;
1257 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1258 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1259 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1260 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1261 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1262 /* if clip is hidden */
1263 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1265 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1266 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1267 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1268 message->param.setup.callerinfo.present = e_ext.callerid_present;
1270 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1271 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1272 //terminal if (e_dialinginfo.id)
1273 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1274 /* handle restricted caller ids */
1275 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);
1276 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);
1277 /* display callerid if desired for extension */
1278 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));
1279 message_put(message);
1280 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1284 check_anycall_intern:
1285 /* now we have all ports created */
1288 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1290 if (!ea_endpoint->ep_join_id)
1292 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1293 return; /* must exit here */
1297 /* *********************** external call */
1299 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1300 /* call to extenal interfaces */
1301 p = e_dialinginfo.id;
1305 while(*p!=',' && *p!='\0')
1306 SCCAT(number, *p++);
1310 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");
1311 /* hunt for mISDNport and create Port */
1312 /* hunt for mISDNport and create Port */
1313 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1316 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1317 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1319 goto check_anycall_extern;
1321 /* creating EXTERNAL port*/
1322 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1323 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)))
1324 FATAL("No memory for DSS1 Port instance\n");
1325 earlyb = mISDNport->earlyb;
1326 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1327 memset(&dialinginfo, 0, sizeof(dialinginfo));
1328 SCPY(dialinginfo.id, number);
1329 dialinginfo.itype = INFO_ITYPE_ISDN;
1330 dialinginfo.ntype = e_dialinginfo.ntype;
1331 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1334 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1336 goto check_anycall_extern;
1338 // dss1 = (class Pdss1 *)port;
1339 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1340 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1341 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1342 SCPY(message->param.setup.dialinginfo.id, number);
1343 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1344 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1345 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1346 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1347 //terminal if (e_dialinginfo.id)
1348 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1349 /* handle restricted caller ids */
1350 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);
1351 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);
1352 /* display callerid if desired for extension */
1353 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));
1354 message_put(message);
1355 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1359 check_anycall_extern:
1360 /* now we have all ports created */
1363 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1365 if (!ea_endpoint->ep_join_id)
1367 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1368 return; /* must exit here */
1376 /* handler for endpoint
1380 int EndpointAppPBX::handler(void)
1382 if (e_crypt_state!=CM_ST_NULL)
1387 /* process answering machine (play) handling */
1390 if (e_action->index == ACTION_VBOX_PLAY)
1393 /* process action timeout */
1394 if (e_action_timeout)
1395 if (now_d >= e_action_timeout)
1397 if (e_state!=EPOINT_STATE_CONNECT)
1400 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1401 e_multipoint_cause = CAUSE_NOUSER;
1402 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
1403 new_state(EPOINT_STATE_IN_OVERLAP);
1406 return(1); /* we must exit, because our endpoint might be gone */
1408 e_action_timeout = 0;
1411 /* process action timeout */
1412 if (e_match_timeout)
1413 if (now_d >= e_match_timeout)
1416 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1418 return(1); /* we must exit, because our endpoint might be gone */
1423 /* process redialing (epoint redials to port) */
1426 if (now_d >= e_redial)
1429 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1431 new_state(EPOINT_STATE_OUT_SETUP);
1432 /* call special setup routine */
1439 /* process powerdialing (epoint redials to epoint) */
1440 if (e_powerdialing > 0)
1442 if (now_d >= e_powerdialing)
1444 e_powerdialing = -1; /* leave power dialing on */
1445 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1448 e_ruleset = ruleset_main;
1450 e_rule = e_ruleset->rule_first;
1452 new_state(EPOINT_STATE_IN_OVERLAP);
1458 /* process call forward no response */
1461 struct port_list *portlist;
1462 struct message *message;
1464 if (now >= e_cfnr_release)
1466 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1469 /* release all ports */
1470 while((portlist = ea_endpoint->ep_portlist))
1472 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1473 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1474 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1475 message_put(message);
1476 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1477 ea_endpoint->free_portlist(portlist);
1480 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1481 message->param.audiopath = CHANNEL_STATE_HOLD;
1482 message_put(message);
1483 /* indicate no patterns */
1484 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1485 message_put(message);
1486 /* set setup state, since we have no response from the new join */
1487 new_state(EPOINT_STATE_OUT_SETUP);
1492 if (now >= e_cfnr_call)
1494 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1500 /* handle connection to user */
1501 if (e_state == EPOINT_STATE_IDLE)
1503 /* epoint is idle, check callback */
1505 if (now_d >= e_callback)
1507 e_callback = 0; /* done with callback */
1508 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1509 new_state(EPOINT_STATE_OUT_SETUP);
1515 /* check for password timeout */
1517 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1519 struct port_list *portlist;
1521 if (now >= e_password_timeout)
1523 e_ruleset = ruleset_main;
1525 e_rule = e_ruleset->rule_first;
1527 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1528 trace_header("PASSWORD timeout", DIRECTION_NONE);
1530 e_connectedmode = 0;
1532 new_state(EPOINT_STATE_OUT_DISCONNECT);
1533 portlist = ea_endpoint->ep_portlist;
1536 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1537 set_tone(portlist, "cause_10");
1547 /* doing a hookflash */
1548 void EndpointAppPBX::hookflash(void)
1552 /* be sure that we are active */
1554 e_tx_state = NOTIFY_STATE_ACTIVE;
1556 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1558 if (ea_endpoint->ep_use > 1)
1560 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1563 /* dialtone after pressing the hash key */
1564 process_hangup(e_join_cause, e_join_location);
1565 e_multipoint_cause = CAUSE_NOUSER;
1566 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
1567 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1570 port->set_echotest(0);
1572 if (ea_endpoint->ep_join_id)
1574 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1576 e_ruleset = ruleset_main;
1578 e_rule = e_ruleset->rule_first;
1580 new_state(EPOINT_STATE_IN_OVERLAP);
1581 e_connectedmode = 1;
1582 SCPY(e_dialinginfo.id, e_ext.prefix);
1583 e_extdialing = e_dialinginfo.id;
1585 if (e_dialinginfo.id[0])
1587 set_tone(ea_endpoint->ep_portlist, "dialing");
1591 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1598 /* messages from port
1600 /* port MESSAGE_SETUP */
1601 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1603 struct message *message;
1605 int writeext; /* flags need to write extension after modification */
1607 struct interface *interface;
1609 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1611 portlist->port_type = param->setup.port_type;
1612 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1613 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1614 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1615 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1616 e_dtmf = param->setup.dtmf;
1618 /* screen incoming caller id */
1619 interface = interface_first;
1622 if (!strcmp(e_callerinfo.interface, interface->name))
1626 interface = interface->next;
1629 screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1631 /* process extension */
1632 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1634 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1635 /* port makes call from extension */
1636 SCPY(e_callerinfo.extension, e_callerinfo.id);
1637 SCPY(e_ext.number, e_callerinfo.extension);
1638 SCPY(e_extension_interface, e_callerinfo.interface);
1641 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1644 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1646 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1648 /* get extension's info about caller */
1649 if (!read_extension(&e_ext, e_ext.number))
1651 /* extension doesn't exist */
1652 trace_header("EXTENSION (not created)", DIRECTION_IN);
1653 add_trace("extension", NULL, "%s", e_ext.number);
1655 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1656 new_state(EPOINT_STATE_OUT_DISCONNECT);
1657 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1658 e_ext.number[0] = '\0'; /* no terminal */
1663 /* put prefix (next) in front of e_dialinginfo.id */
1666 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1667 SCPY(e_dialinginfo.id, buffer);
1668 e_ext.next[0] = '\0';
1670 } else if (e_ext.prefix[0])
1672 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1673 SCPY(e_dialinginfo.id, buffer);
1676 /* screen caller id by extension's config */
1677 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1679 SCPY(e_callerinfo.name, e_ext.name);
1680 /* use caller id (or if exist: id_next_call) for this call */
1681 if (e_ext.id_next_call_present >= 0)
1683 SCPY(e_callerinfo.id, e_ext.id_next_call);
1684 /* if we restrict the pesentation */
1685 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1686 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1687 else e_callerinfo.present = e_ext.id_next_call_present;
1688 e_callerinfo.ntype = e_ext.id_next_call_type;
1689 e_ext.id_next_call_present = -1;
1693 SCPY(e_callerinfo.id, e_ext.callerid);
1694 /* if we restrict the pesentation */
1695 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1696 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1697 else e_callerinfo.present = e_ext.callerid_present;
1698 e_callerinfo.ntype = e_ext.callerid_type;
1701 /* extension is written */
1703 write_extension(&e_ext, e_ext.number);
1705 /* set volume of rx and tx */
1706 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1707 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
1709 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1710 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1711 message->param.mISDNsignal.rxvol = e_ext.txvol;
1712 message->param.mISDNsignal.txvol = e_ext.rxvol;
1713 message_put(message);
1716 /* start recording if enabled */
1717 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1719 /* check if we are a terminal */
1720 if (e_ext.number[0] == '\0')
1721 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1724 port = find_port_id(portlist->port_id);
1726 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1731 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1732 /* no terminal identification */
1733 e_ext.number[0] = '\0';
1734 e_extension_interface[0] = '\0';
1735 memset(&e_ext, 0, sizeof(e_ext));
1736 e_ext.rights = 4; /* right to dial internat */
1740 e_ruleset = ruleset_main;
1742 e_rule = e_ruleset->rule_first;
1744 e_extdialing = e_dialinginfo.id;
1745 new_state(EPOINT_STATE_IN_SETUP);
1746 if (e_dialinginfo.id[0])
1748 set_tone(portlist, "dialing");
1751 if (e_ext.number[0])
1752 set_tone(portlist, "dialpbx");
1754 set_tone(portlist, "dialtone");
1757 if (e_state == EPOINT_STATE_IN_SETUP)
1759 /* request MORE info, if not already at higher state */
1760 new_state(EPOINT_STATE_IN_OVERLAP);
1761 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1762 message_put(message);
1763 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1767 /* port MESSAGE_INFORMATION */
1768 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1770 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1774 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1777 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);
1781 /* if vbox_play is done, the information are just used as they come */
1783 if (e_action->index == ACTION_VBOX_PLAY)
1785 /* concat dialing string */
1786 SCAT(e_dialinginfo.id, param->information.id);
1791 /* keypad when disconnect but in connected mode */
1792 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1794 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1795 /* processing keypad function */
1796 if (param->information.id[0] == '0')
1803 /* keypad when connected */
1804 if (e_state == EPOINT_STATE_CONNECT && e_ext.keypad)
1806 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1807 /* processing keypad function */
1808 if (param->information.id[0] == '0')
1812 if (param->information.id[0])
1813 keypad_function(param->information.id[0]);
1816 if (e_state != EPOINT_STATE_IN_OVERLAP)
1818 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in overlap, or connect state.\n", ea_endpoint->ep_serial);
1821 if (!param->information.id[0])
1823 if (e_dialinginfo.id[0]=='\0' && !e_action)
1825 set_tone(portlist, "dialing");
1828 if (e_action->index==ACTION_OUTDIAL
1829 || e_action->index==ACTION_EXTERNAL)
1832 set_tone(portlist, "dialing");
1833 else if (!e_extdialing[0])
1834 set_tone(portlist, "dialing");
1836 /* concat dialing string */
1837 SCAT(e_dialinginfo.id, param->information.id);
1841 /* port MESSAGE_DTMF */
1842 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1844 trace_header("DTMF", DIRECTION_IN);
1845 add_trace("digit", NULL, "%c", param->dtmf);
1847 /* only if dtmf detection is enabled */
1850 PDEBUG(DEBUG_EPOINT, "dtmf detection is disabled\n");
1855 NOTE: vbox is now handled due to overlap state
1856 /* if vbox_play is done, the dtmf digits are just used as they come */
1858 if (e_action->index == ACTION_VBOX_PLAY)
1860 /* concat dialing string */
1861 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1863 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1864 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1867 /* continue to process *X# sequences */
1871 /* check for *X# sequence */
1872 if (e_state == EPOINT_STATE_CONNECT)
1874 if (e_dtmf_time+3 < now)
1876 /* the last digit was too far in the past to be a sequence */
1877 if (param->dtmf == '*')
1878 /* only start is allowed in the sequence */
1884 /* we have a sequence of digits, see what we got */
1885 if (param->dtmf == '*')
1887 else if (param->dtmf>='0' && param->dtmf<='9')
1889 /* we need to have a star before we receive the digit of the sequence */
1890 if (e_dtmf_last == '*')
1891 e_dtmf_last = param->dtmf;
1892 } else if (param->dtmf == '#')
1895 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1897 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1898 if (e_dtmf_last == '0')
1903 /* processing keypad function */
1905 keypad_function(e_dtmf_last);
1911 /* set last time of dtmf */
1916 /* check for ## hookflash during dialing */
1918 if (e_action->index==ACTION_PASSWORD
1919 || e_action->index==ACTION_PASSWORD_WRITE)
1921 if (param->dtmf=='#') /* current digit is '#' */
1923 if (e_state==EPOINT_STATE_IN_DISCONNECT
1924 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1941 /* dialing using dtmf digit */
1942 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1944 if (e_dialinginfo.id[0]=='\0' && !e_action)
1946 set_tone(portlist, "dialing");
1948 /* concat dialing string */
1949 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1951 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1952 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1958 /* port MESSAGE_CRYPT */
1959 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1961 /* send crypt response to cryptman */
1962 if (param->crypt.type == CR_MESSAGE_IND)
1963 cryptman_msg2man(param->crypt.data, param->crypt.len);
1965 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1968 /* port MESSAGE_OVERLAP */
1969 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1971 struct message *message;
1973 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1975 /* signal to call tool */
1976 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1978 if (e_dialing_queue[0] && portlist)
1980 /* send what we have not dialed yet, because we had no setup complete */
1981 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1982 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1983 SCPY(message->param.information.id, e_dialing_queue);
1984 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1985 message_put(message);
1986 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1987 e_dialing_queue[0] = '\0';
1989 /* check if pattern is available */
1990 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
1992 /* indicate patterns */
1993 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1994 message_put(message);
1996 /* connect audio, if not already */
1997 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1998 message->param.audiopath = CHANNEL_STATE_CONNECT;
1999 message_put(message);
2002 /* indicate no patterns */
2003 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2004 message_put(message);
2006 /* disconnect audio, if not already */
2007 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2008 message->param.audiopath = CHANNEL_STATE_HOLD;
2009 message_put(message);
2011 new_state(EPOINT_STATE_OUT_OVERLAP);
2012 /* if we are in a join */
2013 if (ea_endpoint->ep_join_id)
2015 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2016 memcpy(&message->param, param, sizeof(union parameter));
2017 message_put(message);
2021 /* port MESSAGE_PROCEEDING */
2022 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2024 struct message *message;
2026 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2028 /* signal to call tool */
2029 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
2031 e_state = EPOINT_STATE_OUT_PROCEEDING;
2032 /* check if pattern is availatle */
2033 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2035 /* indicate patterns */
2036 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2037 message_put(message);
2039 /* connect audio, if not already */
2040 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2041 message->param.audiopath = CHANNEL_STATE_CONNECT;
2042 message_put(message);
2045 /* indicate no patterns */
2046 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2047 message_put(message);
2049 /* disconnect audio, if not already */
2050 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2051 message->param.audiopath = CHANNEL_STATE_HOLD;
2052 message_put(message);
2054 /* if we are in a call */
2055 if (ea_endpoint->ep_join_id)
2057 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2058 memcpy(&message->param, param, sizeof(union parameter));
2059 message_put(message);
2063 /* port MESSAGE_ALERTING */
2064 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
2066 struct message *message;
2068 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2070 /* signal to call tool */
2071 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
2073 new_state(EPOINT_STATE_OUT_ALERTING);
2074 /* check if pattern is available */
2075 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2077 /* indicate patterns */
2078 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2079 message_put(message);
2081 /* connect audio, if not already */
2082 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2083 message->param.audiopath = CHANNEL_STATE_CONNECT;
2084 message_put(message);
2087 /* indicate no patterns */
2088 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2089 message_put(message);
2091 /* disconnect audio, if not already */
2092 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2093 message->param.audiopath = CHANNEL_STATE_HOLD;
2094 message_put(message);
2096 /* if we are in a call */
2097 if (ea_endpoint->ep_join_id)
2099 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2100 memcpy(&message->param, param, sizeof(union parameter));
2101 message_put(message);
2105 /* port MESSAGE_CONNECT */
2106 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2108 struct message *message;
2110 unsigned long port_id = portlist->port_id;
2111 struct port_list *tportlist;
2113 struct interface *interface;
2115 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2117 /* signal to call tool */
2118 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2120 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2121 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2122 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2124 tportlist = ea_endpoint->ep_portlist;
2125 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2126 tportlist = tportlist->next;
2127 if (tportlist->port_id == port_id)
2128 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2129 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2130 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2131 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2132 message_put(message);
2133 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2134 ea_endpoint->free_portlist(tportlist);
2136 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2140 /* screen incoming connected id */
2141 interface = interface_first;
2144 if (!strcmp(e_connectinfo.interface, interface->name))
2148 interface = interface->next;
2151 screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2153 /* screen connected name */
2155 SCPY(e_connectinfo.name, e_ext.name);
2157 /* add internal id to colp */
2158 SCPY(e_connectinfo.extension, e_ext.number);
2160 /* we store the connected port number */
2161 SCPY(e_extension_interface, e_connectinfo.interface);
2163 /* for internal and am calls, we get the extension's id */
2164 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2166 SCPY(e_connectinfo.id, e_ext.callerid);
2167 SCPY(e_connectinfo.extension, e_ext.number);
2168 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2169 e_connectinfo.ntype = e_ext.callerid_type;
2170 e_connectinfo.present = e_ext.callerid_present;
2172 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2174 e_connectinfo.itype = INFO_ITYPE_VBOX;
2175 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2178 new_state(EPOINT_STATE_CONNECT);
2180 /* set volume of rx and tx */
2181 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2183 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2184 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2185 message->param.mISDNsignal.rxvol = e_ext.txvol;
2186 message->param.mISDNsignal.txvol = e_ext.rxvol;
2187 message_put(message);
2190 e_cfnr_call = e_cfnr_release = 0;
2191 if (e_ext.number[0])
2192 e_dtmf = 1; /* allow dtmf */
2193 // if (call_countrelations(ea_endpoint->ep_join_id) == 2)
2196 /* other calls with no caller id (or not available for the extension) and force colp */
2197 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2199 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2200 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2202 port = find_port_id(portlist->port_id);
2205 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype));
2206 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2210 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2211 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2212 message_put(message);
2214 if (ea_endpoint->ep_join_id)
2216 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2217 message->param.audiopath = CHANNEL_STATE_CONNECT;
2218 message_put(message);
2219 } else if (!e_adminid)
2222 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2223 SCPY(e_ext.number, e_cbcaller);
2224 new_state(EPOINT_STATE_IN_OVERLAP);
2225 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2227 /* get extension's info about terminal */
2228 if (!read_extension(&e_ext, e_ext.number))
2230 /* extension doesn't exist */
2231 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2232 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2233 new_state(EPOINT_STATE_OUT_DISCONNECT);
2234 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2238 /* put prefix in front of e_cbdialing */
2239 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2240 SCPY(e_dialinginfo.id, buffer);
2241 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2242 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2244 /* use caller id (or if exist: id_next_call) for this call */
2245 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2246 SCPY(e_callerinfo.extension, e_ext.number);
2247 if (e_ext.id_next_call_present >= 0)
2249 SCPY(e_callerinfo.id, e_ext.id_next_call);
2250 e_callerinfo.present = e_ext.id_next_call_present;
2251 e_callerinfo.ntype = e_ext.id_next_call_type;
2252 e_ext.id_next_call_present = -1;
2253 /* extension is written */
2254 write_extension(&e_ext, e_ext.number);
2257 SCPY(e_callerinfo.id, e_ext.callerid);
2258 e_callerinfo.present = e_ext.callerid_present;
2259 e_callerinfo.ntype = e_ext.callerid_type;
2262 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2265 /* check if caller id is NOT authenticated */
2266 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2268 /* make call state to enter password */
2269 new_state(EPOINT_STATE_IN_OVERLAP);
2270 e_action = &action_password_write;
2271 e_match_timeout = 0;
2272 e_match_to_action = NULL;
2273 e_dialinginfo.id[0] = '\0';
2274 e_extdialing = strchr(e_dialinginfo.id, '\0');
2275 e_password_timeout = now+20;
2279 /* incoming call (callback) */
2280 e_ruleset = ruleset_main;
2282 e_rule = e_ruleset->rule_first;
2284 e_extdialing = e_dialinginfo.id;
2285 if (e_dialinginfo.id[0])
2287 set_tone(portlist, "dialing");
2291 set_tone(portlist, "dialpbx");
2294 } else /* testcall */
2296 set_tone(portlist, "hold");
2299 /* start recording if enabled, not when answering machine answers */
2300 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))
2302 /* check if we are a terminal */
2303 if (e_ext.number[0] == '\0')
2304 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2307 port = find_port_id(portlist->port_id);
2309 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2314 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2315 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2317 struct message *message;
2319 unsigned long port_id = portlist->port_id;
2323 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2325 /* signal to call tool */
2326 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2328 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2329 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2331 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2336 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);
2337 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2338 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2340 /* check if we have more than one portlist relation and we just ignore the disconnect */
2341 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2343 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2344 portlist = ea_endpoint->ep_portlist;
2347 if (portlist->port_id == port_id)
2349 portlist = portlist->next;
2352 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2353 if (message_type != MESSAGE_RELEASE)
2355 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2356 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2357 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2358 message_put(message);
2359 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2361 ea_endpoint->free_portlist(portlist);
2362 return; /* one relation removed */
2364 if (e_state == EPOINT_STATE_CONNECT)
2366 /* use cause from port after connect */
2367 cause = param->disconnectinfo.cause;
2368 location = param->disconnectinfo.location;
2371 /* use multipoint cause if no connect yet */
2372 cause = e_multipoint_cause;
2373 location = e_multipoint_location;
2376 e_cfnr_call = e_cfnr_release = 0;
2378 /* process hangup */
2379 process_hangup(e_join_cause, e_join_location);
2380 e_multipoint_cause = 0;
2381 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
2383 if (message_type == MESSAGE_DISCONNECT)
2385 /* tone to disconnected end */
2386 SPRINT(buffer, "cause_%02x", cause);
2387 if (ea_endpoint->ep_portlist)
2388 set_tone(ea_endpoint->ep_portlist, buffer);
2390 new_state(EPOINT_STATE_IN_DISCONNECT);
2393 if (ea_endpoint->ep_join_id)
2395 int haspatterns = 0;
2396 /* check if pattern is available */
2397 if (ea_endpoint->ep_portlist)
2398 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2399 if (joinpbx_countrelations(ea_endpoint->ep_join_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
2400 && message_type != MESSAGE_RELEASE) // if we release, we are done
2404 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2405 /* indicate patterns */
2406 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2407 message_put(message);
2408 /* connect audio, if not already */
2409 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2410 message->param.audiopath = CHANNEL_STATE_CONNECT;
2411 message_put(message);
2412 /* send disconnect */
2413 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2414 memcpy(&message->param, param, sizeof(union parameter));
2415 message_put(message);
2416 /* disable encryption if disconnected */
2417 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2419 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2423 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2426 if (message_type == MESSAGE_RELEASE)
2427 ea_endpoint->free_portlist(portlist);
2428 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2429 return; /* must exit here */
2432 /* port MESSAGE_TIMEOUT */
2433 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2437 trace_header("TIMEOUT", DIRECTION_IN);
2438 message_type = MESSAGE_DISCONNECT;
2439 switch (param->state)
2441 case PORT_STATE_OUT_SETUP:
2442 case PORT_STATE_OUT_OVERLAP:
2443 add_trace("state", NULL, "outgoing setup/dialing");
2445 /* no user responding */
2446 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2447 return; /* must exit here */
2449 case PORT_STATE_IN_SETUP:
2450 case PORT_STATE_IN_OVERLAP:
2451 add_trace("state", NULL, "incoming setup/dialing");
2452 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2453 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2456 case PORT_STATE_OUT_PROCEEDING:
2457 add_trace("state", NULL, "outgoing proceeding");
2459 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2460 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2461 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2462 return; /* must exit here */
2464 case PORT_STATE_IN_PROCEEDING:
2465 add_trace("state", NULL, "incoming proceeding");
2466 param->disconnectinfo.cause = CAUSE_NOUSER;
2467 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2470 case PORT_STATE_OUT_ALERTING:
2471 add_trace("state", NULL, "outgoing alerting");
2473 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2474 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2475 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2476 return; /* must exit here */
2478 case PORT_STATE_CONNECT:
2479 add_trace("state", NULL, "connect");
2481 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2482 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2483 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2484 return; /* must exit here */
2486 case PORT_STATE_IN_ALERTING:
2487 add_trace("state", NULL, "incoming alerting");
2488 param->disconnectinfo.cause = CAUSE_NOANSWER;
2489 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2492 case PORT_STATE_IN_DISCONNECT:
2493 case PORT_STATE_OUT_DISCONNECT:
2494 add_trace("state", NULL, "disconnect");
2496 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2497 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2498 return; /* must exit here */
2501 param->disconnectinfo.cause = 31; /* normal unspecified */
2502 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2505 /* release call, disconnect isdn */
2507 new_state(EPOINT_STATE_OUT_DISCONNECT);
2508 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2509 SCPY(e_tone, cause);
2512 set_tone(portlist, cause);
2513 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2514 portlist = portlist->next;
2516 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2519 /* port MESSAGE_NOTIFY */
2520 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2522 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2524 struct message *message;
2528 /* signal to call tool */
2529 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2530 if (param->notifyinfo.notify)
2532 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2535 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2536 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2538 case INFO_NOTIFY_REMOTE_HOLD:
2539 case INFO_NOTIFY_USER_SUSPENDED:
2540 /* tell call about it */
2541 if (ea_endpoint->ep_join_id)
2543 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2544 message->param.audiopath = CHANNEL_STATE_HOLD;
2545 message_put(message);
2549 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2550 case INFO_NOTIFY_USER_RESUMED:
2551 /* set volume of rx and tx */
2552 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2553 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2556 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2557 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2558 message->param.mISDNsignal.rxvol = e_ext.txvol;
2559 message->param.mISDNsignal.txvol = e_ext.rxvol;
2560 message_put(message);
2562 /* set current tone */
2564 set_tone(portlist, e_tone);
2565 /* tell call about it */
2566 if (ea_endpoint->ep_join_id)
2568 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2569 message->param.audiopath = CHANNEL_STATE_CONNECT;
2570 message_put(message);
2575 /* get name of notify */
2576 switch(param->notifyinfo.notify)
2582 logtext = "USER_SUSPENDED";
2585 logtext = "BEARER_SERVICE_CHANGED";
2588 logtext = "USER_RESUMED";
2591 logtext = "CONFERENCE_ESTABLISHED";
2594 logtext = "CONFERENCE_DISCONNECTED";
2597 logtext = "OTHER_PARTY_ADDED";
2600 logtext = "ISOLATED";
2603 logtext = "REATTACHED";
2606 logtext = "OTHER_PARTY_ISOLATED";
2609 logtext = "OTHER_PARTY_REATTACHED";
2612 logtext = "OTHER_PARTY_SPLIT";
2615 logtext = "OTHER_PARTY_DISCONNECTED";
2618 logtext = "CONFERENCE_FLOATING";
2621 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2624 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2627 logtext = "CALL_IS_A_WAITING_CALL";
2630 logtext = "DIVERSION_ACTIVATED";
2633 logtext = "RESERVED_CT_1";
2636 logtext = "RESERVED_CT_2";
2639 logtext = "REVERSE_CHARGING";
2642 logtext = "REMOTE_HOLD";
2645 logtext = "REMOTE_RETRIEVAL";
2648 logtext = "CALL_IS_DIVERTING";
2651 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2656 /* notify call if available */
2657 if (ea_endpoint->ep_join_id)
2659 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2660 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2661 message_put(message);
2666 /* port MESSAGE_FACILITY */
2667 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2669 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2671 struct message *message;
2673 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2674 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2675 message_put(message);
2678 /* port MESSAGE_SUSPEND */
2679 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2680 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2682 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2684 /* epoint is now parked */
2685 ea_endpoint->ep_park = 1;
2686 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2687 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2689 /* remove port relation */
2690 ea_endpoint->free_portlist(portlist);
2693 /* port MESSAGE_RESUME */
2694 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2695 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2697 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2699 /* epoint is now resumed */
2700 ea_endpoint->ep_park = 0;
2705 /* port sends message to the endpoint
2707 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2709 struct port_list *portlist;
2710 struct message *message;
2712 portlist = ea_endpoint->ep_portlist;
2715 if (port_id == portlist->port_id)
2717 portlist = portlist->next;
2721 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);
2725 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2726 switch(message_type)
2728 case MESSAGE_DATA: /* data from port */
2729 /* check if there is a call */
2730 if (!ea_endpoint->ep_join_id)
2732 /* continue if only one portlist */
2733 if (ea_endpoint->ep_portlist->next != NULL)
2735 /* forward message */
2736 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2739 case MESSAGE_TONE_EOF: /* tone is end of file */
2740 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2743 if (e_action->index == ACTION_VBOX_PLAY)
2747 if (e_action->index == ACTION_EFI)
2754 case MESSAGE_TONE_COUNTER: /* counter info received */
2755 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);
2757 if (e_action->index == ACTION_VBOX_PLAY)
2759 e_vbox_counter = param->counter.current;
2760 if (param->counter.max >= 0)
2761 e_vbox_counter_max = param->counter.max;
2765 /* PORT sends SETUP message */
2767 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);
2768 if (e_state!=EPOINT_STATE_IDLE)
2770 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2773 port_setup(portlist, message_type, param);
2776 /* PORT sends INFORMATION message */
2777 case MESSAGE_INFORMATION: /* additional digits received */
2778 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);
2779 port_information(portlist, message_type, param);
2782 /* PORT sends FACILITY message */
2783 case MESSAGE_FACILITY:
2784 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2785 port_facility(portlist, message_type, param);
2788 /* PORT sends DTMF message */
2789 case MESSAGE_DTMF: /* dtmf digits received */
2790 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);
2791 port_dtmf(portlist, message_type, param);
2794 /* PORT sends CRYPT message */
2795 case MESSAGE_CRYPT: /* crypt response received */
2796 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2797 port_crypt(portlist, message_type, param);
2800 /* PORT sends MORE message */
2801 case MESSAGE_OVERLAP:
2802 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);
2803 if (e_state != EPOINT_STATE_OUT_SETUP)
2805 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);
2808 port_overlap(portlist, message_type, param);
2811 /* PORT sends PROCEEDING message */
2812 case MESSAGE_PROCEEDING: /* port is proceeding */
2813 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);
2814 if (e_state!=EPOINT_STATE_OUT_SETUP
2815 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2817 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);
2820 port_proceeding(portlist, message_type, param);
2823 /* PORT sends ALERTING message */
2824 case MESSAGE_ALERTING:
2825 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);
2826 if (e_state!=EPOINT_STATE_OUT_SETUP
2827 && e_state!=EPOINT_STATE_OUT_OVERLAP
2828 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2830 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);
2833 port_alerting(portlist, message_type, param);
2836 /* PORT sends CONNECT message */
2837 case MESSAGE_CONNECT:
2838 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);
2839 if (e_state!=EPOINT_STATE_OUT_SETUP
2840 && e_state!=EPOINT_STATE_OUT_OVERLAP
2841 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2842 && e_state!=EPOINT_STATE_OUT_ALERTING)
2844 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2847 port_connect(portlist, message_type, param);
2850 /* PORT sends DISCONNECT message */
2851 case MESSAGE_DISCONNECT: /* port is disconnected */
2852 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);
2853 port_disconnect_release(portlist, message_type, param);
2856 /* PORT sends a RELEASE message */
2857 case MESSAGE_RELEASE: /* port releases */
2858 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);
2859 /* portlist is release at port_disconnect_release, thanx Paul */
2860 port_disconnect_release(portlist, message_type, param);
2863 /* PORT sends a TIMEOUT message */
2864 case MESSAGE_TIMEOUT:
2865 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);
2866 port_timeout(portlist, message_type, param);
2867 break; /* release */
2869 /* PORT sends a NOTIFY message */
2870 case MESSAGE_NOTIFY:
2871 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);
2872 port_notify(portlist, message_type, param);
2875 /* PORT sends a SUSPEND message */
2876 case MESSAGE_SUSPEND:
2877 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);
2878 port_suspend(portlist, message_type, param);
2879 break; /* suspend */
2881 /* PORT sends a RESUME message */
2882 case MESSAGE_RESUME:
2883 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);
2884 port_resume(portlist, message_type, param);
2888 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);
2891 /* Note: this endpoint may be destroyed, so we MUST return */
2895 /* messages from join
2897 /* join MESSAGE_CRYPT */
2898 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2900 switch(param->crypt.type)
2902 /* message from remote port to "crypt manager" */
2903 case CU_ACTK_REQ: /* activate key-exchange */
2904 case CU_ACTS_REQ: /* activate shared key */
2905 case CU_DACT_REQ: /* deactivate */
2906 case CU_INFO_REQ: /* request last info message */
2907 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2910 /* message from "crypt manager" to user */
2911 case CU_ACTK_CONF: /* key-echange done */
2912 case CU_ACTS_CONF: /* shared key done */
2913 case CU_DACT_CONF: /* deactivated */
2914 case CU_DACT_IND: /* deactivated */
2915 case CU_ERROR_IND: /* receive error message */
2916 case CU_INFO_IND: /* receive info message */
2917 case CU_INFO_CONF: /* receive info message */
2918 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2922 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);
2926 /* join MESSAGE_INFORMATION */
2927 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2929 struct message *message;
2935 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2936 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2937 message_put(message);
2938 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2939 portlist = portlist->next;
2943 /* join MESSAGE_FACILITY */
2944 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2946 struct message *message;
2948 if (!e_ext.facility)
2955 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2956 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2957 message_put(message);
2958 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2959 portlist = portlist->next;
2963 /* join MESSAGE_MORE */
2964 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2966 struct message *message;
2968 new_state(EPOINT_STATE_IN_OVERLAP);
2971 if (e_join_pattern && e_ext.own_setup)
2973 /* disconnect audio */
2974 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2975 message->param.audiopath = CHANNEL_STATE_HOLD;
2976 message_put(message);
2978 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2980 set_tone(portlist, "dialtone");
2983 if (e_ext.number[0])
2984 set_tone(portlist, "dialpbx");
2986 set_tone(portlist, "dialtone");
2989 /* join MESSAGE_PROCEEDING */
2990 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2992 struct message *message;
2994 new_state(EPOINT_STATE_IN_PROCEEDING);
2996 /* own proceeding tone */
2999 /* connect / disconnect audio */
3000 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3001 if (e_ext.own_proceeding)
3002 message->param.audiopath = CHANNEL_STATE_HOLD;
3004 message->param.audiopath = CHANNEL_STATE_CONNECT;
3005 message_put(message);
3007 // UCPY(e_join_tone, "proceeding");
3010 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3011 message_put(message);
3012 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3014 set_tone(portlist, "proceeding");
3017 /* join MESSAGE_ALERTING */
3018 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
3020 struct message *message;
3022 new_state(EPOINT_STATE_IN_ALERTING);
3024 /* own alerting tone */
3027 /* connect / disconnect audio */
3028 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3029 if (e_ext.own_alerting)
3030 message->param.audiopath = CHANNEL_STATE_HOLD;
3032 message->param.audiopath = CHANNEL_STATE_CONNECT;
3033 message_put(message);
3037 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
3038 message_put(message);
3039 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3041 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3043 set_tone(portlist, "ringing");
3046 if (e_ext.number[0])
3047 set_tone(portlist, "ringpbx");
3049 set_tone(portlist, "ringing");
3052 /* join MESSAGE_CONNECT */
3053 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
3055 struct message *message;
3056 struct interface *interface;
3058 new_state(EPOINT_STATE_CONNECT);
3059 // UCPY(e_join_tone, "");
3060 if (e_ext.number[0])
3061 e_dtmf = 1; /* allow dtmf */
3063 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
3066 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3067 memcpy(&message->param, param, sizeof(union parameter));
3068 /* screen incoming caller id */
3069 interface = interface_first;
3072 if (!strcmp(e_connectinfo.interface, interface->name))
3076 interface = interface->next;
3079 screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
3080 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(e_connectinfo));
3082 /* screen clip if prefix is required */
3083 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3085 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3086 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
3087 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3090 /* use internal caller id */
3091 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3093 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
3094 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3097 /* handle restricted caller ids */
3098 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);
3099 /* display callerid if desired for extension */
3100 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));
3102 /* use conp, if enabld */
3104 message->param.connectinfo.name[0] = '\0';
3107 message_put(message);
3108 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3110 set_tone(portlist, NULL);
3112 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3113 message->param.audiopath = CHANNEL_STATE_CONNECT;
3114 message_put(message);
3118 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3119 void EndpointAppPBX::join_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
3122 struct message *message;
3125 /* be sure that we are active */
3127 e_tx_state = NOTIFY_STATE_ACTIVE;
3129 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3130 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3132 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3134 /* set time for power dialing */
3135 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3138 /* set redial tone */
3139 if (ea_endpoint->ep_portlist)
3143 set_tone(ea_endpoint->ep_portlist, "redial");
3144 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);
3145 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3146 if (e_state==EPOINT_STATE_IN_OVERLAP)
3148 new_state(EPOINT_STATE_IN_PROCEEDING);
3151 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3152 message_put(message);
3153 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3155 /* caused the error, that the first knock sound was not there */
3156 /* set_tone(portlist, "proceeding"); */
3158 /* send display of powerdialing */
3159 if (e_ext.display_dialing)
3163 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3165 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3167 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3168 message_put(message);
3169 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3170 portlist = portlist->next;
3179 if ((e_state!=EPOINT_STATE_CONNECT
3180 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3181 && e_state!=EPOINT_STATE_IN_OVERLAP
3182 && e_state!=EPOINT_STATE_IN_PROCEEDING
3183 && e_state!=EPOINT_STATE_IN_ALERTING)
3184 || !ea_endpoint->ep_portlist) /* or no port */
3186 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3187 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3188 return; /* must exit here */
3193 e_join_cause = param->disconnectinfo.cause;
3194 e_join_location = param->disconnectinfo.location;
3197 /* on release we need the audio again! */
3198 if (message_type == MESSAGE_RELEASE)
3201 ea_endpoint->ep_join_id = 0;
3203 /* disconnect and select tone */
3204 new_state(EPOINT_STATE_OUT_DISCONNECT);
3205 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3206 /* if own_cause, we must release the join */
3207 if (e_ext.own_cause /* own cause */
3208 || !e_join_pattern) /* no patterns */
3210 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_join_pattern);
3211 if (message_type != MESSAGE_RELEASE)
3212 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3214 } else /* else we enable audio */
3216 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3217 message->param.audiopath = CHANNEL_STATE_CONNECT;
3218 message_put(message);
3220 /* send disconnect message */
3221 SCPY(e_tone, cause);
3224 set_tone(portlist, cause);
3225 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3226 portlist = portlist->next;
3230 /* join MESSAGE_SETUP */
3231 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3233 struct message *message;
3234 struct interface *interface;
3236 /* if we already in setup state, we just update the dialing with new digits */
3237 if (e_state == EPOINT_STATE_OUT_SETUP
3238 || e_state == EPOINT_STATE_OUT_OVERLAP)
3240 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3241 /* if digits changed, what we have already dialed */
3242 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3244 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);
3245 /* release all ports */
3246 while((portlist = ea_endpoint->ep_portlist))
3248 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3249 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3250 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3251 message_put(message);
3252 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3253 ea_endpoint->free_portlist(portlist);
3256 /* disconnect audio */
3257 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3258 message->param.audiopath = CHANNEL_STATE_HOLD;
3259 message_put(message);
3261 /* get dialing info */
3262 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3263 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3264 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3265 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3266 new_state(EPOINT_STATE_OUT_OVERLAP);
3269 e_redial = now_d + 1; /* set redial one second in the future */
3272 /* if we have a pending redial, so we just adjust the dialing number */
3275 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);
3276 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3279 if (!ea_endpoint->ep_portlist)
3281 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3283 if (ea_endpoint->ep_portlist->next)
3285 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3287 if (e_state == EPOINT_STATE_OUT_SETUP)
3290 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);
3291 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3295 /* get what we have not dialed yet */
3296 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));
3297 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3298 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3299 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3300 message_put(message);
3301 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3303 /* always store what we have dialed or queued */
3304 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3308 if (e_state != EPOINT_STATE_IDLE)
3310 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3313 /* if an internal extension is dialed, copy that number */
3314 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3315 SCPY(e_ext.number, param->setup.dialinginfo.id);
3316 /* if an internal extension is dialed, get extension's info about caller */
3317 if (e_ext.number[0])
3319 if (!read_extension(&e_ext, e_ext.number))
3321 e_ext.number[0] = '\0';
3322 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3326 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3327 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3328 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3329 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3331 /* screen incoming caller id */
3332 interface = interface_first;
3335 if (!strcmp(e_callerinfo.interface, interface->name))
3339 interface = interface->next;
3342 screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
3344 /* process (voice over) data calls */
3345 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3347 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3348 memset(&e_capainfo, 0, sizeof(e_capainfo));
3349 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3350 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3351 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3354 new_state(EPOINT_STATE_OUT_SETUP);
3355 /* call special setup routine */
3359 /* join MESSAGE_mISDNSIGNAL */
3360 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3362 struct message *message;
3366 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3367 memcpy(&message->param, param, sizeof(union parameter));
3368 message_put(message);
3369 portlist = portlist->next;
3373 /* join MESSAGE_NOTIFY */
3374 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3376 struct message *message;
3379 if (param->notifyinfo.notify)
3381 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3382 // /* if notification was generated locally, we turn hold music on/off */
3383 // if (param->notifyinfo.local)
3384 // 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)
3389 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3393 set_tone(portlist, "");
3394 portlist = portlist->next;
3396 portlist = ea_endpoint->ep_portlist;
3401 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3405 set_tone(portlist, "hold");
3406 portlist = portlist->next;
3408 portlist = ea_endpoint->ep_portlist;
3413 /* save new state */
3414 e_tx_state = new_state;
3417 /* notify port(s) about it */
3420 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3421 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3422 /* handle restricted caller ids */
3423 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);
3424 /* display callerid if desired for extension */
3425 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));
3426 message_put(message);
3427 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3428 portlist = portlist->next;
3432 /* call sends messages to the endpoint
3434 void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, union parameter *param)
3436 struct port_list *portlist;
3437 struct message *message;
3441 PERROR("EPOINT(%d) error: call == NULL.\n", ea_endpoint->ep_serial);
3445 portlist = ea_endpoint->ep_portlist;
3447 /* send MESSAGE_DATA to port */
3448 if (message_type == MESSAGE_DATA)
3450 if (join_id == ea_endpoint->ep_join_id) // still linked with call
3452 /* skip if no port relation */
3455 /* skip if more than one port relation */
3458 /* forward audio data to port */
3459 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3464 // 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);
3465 switch(message_type)
3467 /* CALL SENDS CRYPT message */
3469 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);
3470 join_crypt(portlist, message_type, param);
3473 /* CALL sends INFORMATION message */
3474 case MESSAGE_INFORMATION:
3475 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);
3476 join_information(portlist, message_type, param);
3479 /* CALL sends FACILITY message */
3480 case MESSAGE_FACILITY:
3481 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);
3482 join_facility(portlist, message_type, param);
3485 /* CALL sends OVERLAP message */
3486 case MESSAGE_OVERLAP:
3487 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);
3488 if (e_state!=EPOINT_STATE_IN_SETUP
3489 && e_state!=EPOINT_STATE_IN_OVERLAP)
3491 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3494 join_overlap(portlist, message_type, param);
3497 /* CALL sends PROCEEDING message */
3498 case MESSAGE_PROCEEDING:
3499 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);
3500 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3502 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3505 join_proceeding(portlist, message_type, param);
3508 /* CALL sends ALERTING message */
3509 case MESSAGE_ALERTING:
3510 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);
3511 if (e_state!=EPOINT_STATE_IN_OVERLAP
3512 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3514 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3517 join_alerting(portlist, message_type, param);
3520 /* CALL sends CONNECT message */
3521 case MESSAGE_CONNECT:
3522 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);
3523 if (e_state!=EPOINT_STATE_IN_OVERLAP
3524 && e_state!=EPOINT_STATE_IN_PROCEEDING
3525 && e_state!=EPOINT_STATE_IN_ALERTING)
3527 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3530 join_connect(portlist, message_type, param);
3533 /* CALL sends DISCONNECT/RELEASE message */
3534 case MESSAGE_DISCONNECT: /* call disconnect */
3535 case MESSAGE_RELEASE: /* call releases */
3536 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);
3537 join_disconnect_release(portlist, message_type, param);
3540 /* CALL sends SETUP message */
3542 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);
3543 join_setup(portlist, message_type, param);
3547 /* CALL sends special mISDNSIGNAL message */
3548 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3549 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);
3550 join_mISDNsignal(portlist, message_type, param);
3553 /* CALL has pattern available */
3554 case MESSAGE_PATTERN: /* indicating pattern available */
3555 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);
3556 if (!e_join_pattern)
3558 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3563 set_tone(portlist, NULL);
3564 portlist = portlist->next;
3566 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3567 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3568 message->param.audiopath = CHANNEL_STATE_CONNECT;
3569 message_put(message);
3570 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3571 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_REMOTE_AUDIO);
3572 // message->param.audiopath = CHANNEL_STATE_CONNECT;
3573 // message_put(message);
3574 // patterns are available, remote already connected audio
3578 /* CALL has no pattern available */
3579 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3580 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);
3583 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3585 /* disconnect our audio tx and rx */
3586 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3587 message->param.audiopath = CHANNEL_STATE_HOLD;
3588 message_put(message);
3593 /* CALL (dunno at the moment) */
3594 case MESSAGE_REMOTE_AUDIO:
3595 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);
3596 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3597 message->param.audiopath = param->channel;
3598 message_put(message);
3602 /* CALL sends a notify message */
3603 case MESSAGE_NOTIFY:
3604 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);
3605 join_notify(portlist, message_type, param);
3609 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);
3614 /* pick_join will connect the first incoming call found. the endpoint
3615 * will receivce a MESSAGE_CONNECT.
3617 int match_list(char *list, char *item)
3619 char *end, *next = NULL;
3621 /* no list make matching */
3627 /* eliminate white spaces */
3628 while (*list <= ' ')
3635 /* if end of list is reached, we return */
3636 if (list[0] == '\0')
3638 /* if we have more than one entry (left) */
3639 if ((end = strchr(list, ',')))
3642 next = end = strchr(list, '\0');
3643 while (*(end-1) <= ' ')
3645 /* if string part matches item */
3646 if (!strncmp(list, item, end-list))
3652 void EndpointAppPBX::pick_join(char *extensions)
3654 struct message *message;
3655 struct port_list *portlist;
3657 class EndpointAppPBX *eapp, *found;
3659 class JoinPBX *joinpbx;
3660 struct join_relation *relation;
3663 /* find an endpoint that is ringing internally or vbox with higher priority */
3666 eapp = apppbx_first;
3669 if (eapp!=this && ea_endpoint->ep_portlist)
3671 portlist = eapp->ea_endpoint->ep_portlist;
3674 if ((port = find_port_id(portlist->port_id)))
3676 if (port->p_type == PORT_TYPE_VBOX_OUT)
3678 if (match_list(extensions, eapp->e_ext.number))
3685 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3686 && port->p_state==PORT_STATE_OUT_ALERTING)
3687 if (match_list(extensions, eapp->e_ext.number))
3692 portlist = portlist->next;
3700 /* if no endpoint found */
3703 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);
3705 set_tone(ea_endpoint->ep_portlist, "cause_10");
3706 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3707 new_state(EPOINT_STATE_OUT_DISCONNECT);
3712 if (ea_endpoint->ep_join_id)
3714 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3717 if (!eapp->ea_endpoint->ep_join_id)
3719 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3722 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3725 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3728 if (joinpbx->j_type != JOIN_TYPE_PBX)
3730 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3733 joinpbx = (class JoinPBX *)join;
3734 relation = joinpbx->j_relation;
3737 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3740 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3742 relation = relation->next;
3745 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3750 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3752 if (options.deb & DEBUG_EPOINT)
3754 class Join *debug_c = join_first;
3755 class Endpoint *debug_e = epoint_first;
3756 class Port *debug_p = port_first;
3758 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3760 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3763 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3764 debug_c = debug_c->next;
3766 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3769 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3770 debug_e = debug_e->next;
3772 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3775 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3776 debug_p = debug_p->next;
3781 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3782 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3783 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3785 /* connnecting our endpoint */
3786 new_state(EPOINT_STATE_CONNECT);
3788 set_tone(ea_endpoint->ep_portlist, NULL);
3790 /* now we send a release to the ringing endpoint */
3791 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3792 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3793 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3794 message_put(message);
3796 /* we send a connect to the join with our caller id */
3797 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3798 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3799 message->param.connectinfo.present = e_callerinfo.present;
3800 message->param.connectinfo.screen = e_callerinfo.screen;
3801 message->param.connectinfo.itype = e_callerinfo.itype;
3802 message->param.connectinfo.ntype = e_callerinfo.ntype;
3803 message_put(message);
3805 /* we send a connect to our port with the remote callerid */
3806 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3807 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3808 message->param.connectinfo.present = eapp->e_callerinfo.present;
3809 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3810 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3811 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3812 /* handle restricted caller ids */
3813 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);
3814 /* display callerid if desired for extension */
3815 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));
3816 message_put(message);
3818 /* we send a connect to the audio path (not for vbox) */
3819 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3820 message->param.audiopath = CHANNEL_STATE_CONNECT;
3821 message_put(message);
3823 /* beeing paranoid, we make call update */
3824 joinpbx->j_updatebridge = 1;
3826 if (options.deb & DEBUG_EPOINT)
3828 class Join *debug_c = join_first;
3829 class Endpoint *debug_e = epoint_first;
3830 class Port *debug_p = port_first;
3832 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3834 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3837 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3838 debug_c = debug_c->next;
3840 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3843 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3844 debug_e = debug_e->next;
3846 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3849 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3850 debug_p = debug_p->next;
3856 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3858 void EndpointAppPBX::join_join(void)
3860 struct message *message;
3861 struct join_relation *our_relation, *other_relation;
3862 struct join_relation **our_relation_pointer, **other_relation_pointer;
3863 class Join *our_join, *other_join;
3864 class JoinPBX *our_joinpbx, *other_joinpbx;
3865 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3866 class Port *our_port, *other_port;
3867 class Pdss1 *our_pdss1, *other_pdss1;
3869 /* are we a candidate to join a join */
3870 our_join = find_join_id(ea_endpoint->ep_join_id);
3873 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3876 if (our_join->j_type != JOIN_TYPE_PBX)
3878 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3881 our_joinpbx = (class JoinPBX *)our_join;
3882 if (!ea_endpoint->ep_portlist)
3884 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3887 if (!e_ext.number[0])
3889 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3892 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3895 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3898 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3900 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3903 our_pdss1 = (class Pdss1 *)our_port;
3905 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3906 other_eapp = apppbx_first;
3909 if (other_eapp == this)
3911 other_eapp = other_eapp->next;
3914 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint candiate: (ep%d) terminal='%s' port=%s join=%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_join_id);
3915 if (other_eapp->e_ext.number[0] /* has terminal */
3916 && other_eapp->ea_endpoint->ep_portlist /* has port */
3917 && other_eapp->ea_endpoint->ep_join_id) /* has join */
3919 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3920 if (other_port) /* port still exists */
3922 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3923 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3925 other_pdss1 = (class Pdss1 *)other_port;
3926 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);
3927 if (other_pdss1->p_m_hold /* port is on hold */
3928 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3929 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3933 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3937 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3940 other_eapp = other_eapp->next;
3944 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3947 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3949 /* if we have the same join */
3950 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
3952 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
3955 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3958 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3961 if (other_join->j_type != JOIN_TYPE_PBX)
3963 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3966 other_joinpbx = (class JoinPBX *)other_join;
3967 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
3969 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3973 /* remove relation to endpoint for join on hold */
3974 other_relation = other_joinpbx->j_relation;
3975 other_relation_pointer = &other_joinpbx->j_relation;
3976 while(other_relation)
3978 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
3980 /* detach other endpoint on hold */
3981 *other_relation_pointer = other_relation->next;
3982 FREE(other_relation, sizeof(struct join_relation));
3984 other_relation = *other_relation_pointer;
3985 other_eapp->ea_endpoint->ep_join_id = NULL;
3989 /* change join/hold pointer of endpoint to the new join */
3990 temp_epoint = find_epoint_id(other_relation->epoint_id);
3993 if (temp_epoint->ep_join_id == other_join->j_serial)
3994 temp_epoint->ep_join_id = our_join->j_serial;
3997 other_relation_pointer = &other_relation->next;
3998 other_relation = other_relation->next;
4000 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
4002 /* join call relations */
4003 our_relation = our_joinpbx->j_relation;
4004 our_relation_pointer = &our_joinpbx->j_relation;
4007 our_relation_pointer = &our_relation->next;
4008 our_relation = our_relation->next;
4010 *our_relation_pointer = other_joinpbx->j_relation;
4011 other_joinpbx->j_relation = NULL;
4012 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
4014 /* release endpoint on hold */
4015 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
4016 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
4017 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
4018 message_put(message);
4020 /* if we are not a partyline, we get partyline state from other join */
4021 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
4023 /* remove empty join */
4025 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
4027 /* mixer must update */
4028 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
4030 /* we send a retrieve to that endpoint */
4031 // mixer will update the hold-state of the join and send it to the endpoints is changes
4035 /* check if we have an external call
4036 * this is used to check for encryption ability
4038 int EndpointAppPBX::check_external(char **errstr, class Port **port)
4040 struct join_relation *relation;
4042 class JoinPBX *joinpbx;
4043 class Endpoint *epoint;
4045 /* some paranoia check */
4046 if (!ea_endpoint->ep_portlist)
4048 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4049 *errstr = "No Call";
4052 if (!e_ext.number[0])
4054 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4055 *errstr = "No Call";
4059 /* check if we have a join with 2 parties */
4060 join = find_join_id(ea_endpoint->ep_join_id);
4063 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
4064 *errstr = "No Call";
4067 if (join->j_type != JOIN_TYPE_PBX)
4069 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
4070 *errstr = "No PBX Call";
4073 joinpbx = (class JoinPBX *)join;
4074 relation = joinpbx->j_relation;
4077 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
4078 *errstr = "No Call";
4081 if (!relation->next)
4083 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
4084 *errstr = "No Call";
4087 if (relation->next->next)
4089 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4090 *errstr = "Err: Conference";
4093 if (relation->epoint_id == ea_endpoint->ep_serial)
4095 relation = relation->next;
4096 if (relation->epoint_id == ea_endpoint->ep_serial)
4098 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4099 *errstr = "Software Error";
4104 /* check remote port for external call */
4105 epoint = find_epoint_id(relation->epoint_id);
4108 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4109 *errstr = "No Call";
4112 if (!epoint->ep_portlist)
4114 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4115 *errstr = "No Call";
4118 *port = find_port_id(epoint->ep_portlist->port_id);
4121 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4122 *errstr = "No Call";
4125 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4127 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4128 *errstr = "No Ext Call";
4131 if ((*port)->p_state != PORT_STATE_CONNECT)
4133 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4134 *errstr = "No Ext Connect";
4140 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned long port_id, int dir)
4142 char *logtext = "unknown";
4145 switch(message_type)
4148 trace_header("SETUP", dir);
4149 if (dir == DIRECTION_OUT)
4150 add_trace("to", NULL, "CH(%lu)", port_id);
4151 if (dir == DIRECTION_IN)
4152 add_trace("from", NULL, "CH(%lu)", port_id);
4153 if (param->setup.callerinfo.extension[0])
4154 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4155 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype));
4156 switch(param->setup.callerinfo.present)
4158 case INFO_PRESENT_RESTRICTED:
4159 add_trace("caller id", "present", "restricted");
4161 case INFO_PRESENT_ALLOWED:
4162 add_trace("caller id", "present", "allowed");
4165 add_trace("caller id", "present", "not available");
4167 if (param->setup.redirinfo.id[0])
4169 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype));
4170 switch(param->setup.redirinfo.present)
4172 case INFO_PRESENT_RESTRICTED:
4173 add_trace("redir'ing", "present", "restricted");
4175 case INFO_PRESENT_ALLOWED:
4176 add_trace("redir'ing", "present", "allowed");
4179 add_trace("redir'ing", "present", "not available");
4182 if (param->setup.dialinginfo.id[0])
4183 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4187 case MESSAGE_OVERLAP:
4188 trace_header("SETUP ACKNOWLEDGE", dir);
4189 if (dir == DIRECTION_OUT)
4190 add_trace("to", NULL, "CH(%lu)", port_id);
4191 if (dir == DIRECTION_IN)
4192 add_trace("from", NULL, "CH(%lu)", port_id);
4196 case MESSAGE_PROCEEDING:
4197 trace_header("PROCEEDING", dir);
4198 if (dir == DIRECTION_OUT)
4199 add_trace("to", NULL, "CH(%lu)", port_id);
4200 if (dir == DIRECTION_IN)
4201 add_trace("from", NULL, "CH(%lu)", port_id);
4205 case MESSAGE_ALERTING:
4206 trace_header("ALERTING", dir);
4207 if (dir == DIRECTION_OUT)
4208 add_trace("to", NULL, "CH(%lu)", port_id);
4209 if (dir == DIRECTION_IN)
4210 add_trace("from", NULL, "CH(%lu)", port_id);
4214 case MESSAGE_CONNECT:
4215 trace_header("CONNECT", dir);
4216 if (dir == DIRECTION_OUT)
4217 add_trace("to", NULL, "CH(%lu)", port_id);
4218 if (dir == DIRECTION_IN)
4219 add_trace("from", NULL, "CH(%lu)", port_id);
4220 if (param->connectinfo.extension[0])
4221 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4222 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype));
4223 switch(param->connectinfo.present)
4225 case INFO_PRESENT_RESTRICTED:
4226 add_trace("connect id", "present", "restricted");
4228 case INFO_PRESENT_ALLOWED:
4229 add_trace("connect id", "present", "allowed");
4232 add_trace("connect id", "present", "not available");
4237 case MESSAGE_DISCONNECT:
4238 case MESSAGE_RELEASE:
4239 if (message_type == MESSAGE_DISCONNECT)
4240 trace_header("DISCONNECT", dir);
4242 trace_header("RELEASE", dir);
4243 if (dir == DIRECTION_OUT)
4244 add_trace("to", NULL, "CH(%lu)", port_id);
4245 if (dir == DIRECTION_IN)
4246 add_trace("from", NULL, "CH(%lu)", port_id);
4247 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4248 switch(param->disconnectinfo.location)
4251 add_trace("cause", "location", "0-User");
4253 case LOCATION_PRIVATE_LOCAL:
4254 add_trace("cause", "location", "1-Local-PBX");
4256 case LOCATION_PUBLIC_LOCAL:
4257 add_trace("cause", "location", "2-Local-Exchange");
4259 case LOCATION_TRANSIT:
4260 add_trace("cause", "location", "3-Transit");
4262 case LOCATION_PUBLIC_REMOTE:
4263 add_trace("cause", "location", "4-Remote-PBX");
4265 case LOCATION_PRIVATE_REMOTE:
4266 add_trace("cause", "location", "5-Remote-Exchange");
4268 case LOCATION_INTERNATIONAL:
4269 add_trace("cause", "location", "7-International-Exchange");
4271 case LOCATION_BEYOND:
4272 add_trace("cause", "location", "10-Beyond-Interworking");
4275 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4280 case MESSAGE_NOTIFY:
4281 switch(param->notifyinfo.notify)
4287 logtext = "USER_SUSPENDED";
4290 logtext = "BEARER_SERVICE_CHANGED";
4293 logtext = "USER_RESUMED";
4296 logtext = "CONFERENCE_ESTABLISHED";
4299 logtext = "CONFERENCE_DISCONNECTED";
4302 logtext = "OTHER_PARTY_ADDED";
4305 logtext = "ISOLATED";
4308 logtext = "REATTACHED";
4311 logtext = "OTHER_PARTY_ISOLATED";
4314 logtext = "OTHER_PARTY_REATTACHED";
4317 logtext = "OTHER_PARTY_SPLIT";
4320 logtext = "OTHER_PARTY_DISCONNECTED";
4323 logtext = "CONFERENCE_FLOATING";
4326 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4329 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4332 logtext = "CALL_IS_A_WAITING_CALL";
4335 logtext = "DIVERSION_ACTIVATED";
4338 logtext = "RESERVED_CT_1";
4341 logtext = "RESERVED_CT_2";
4344 logtext = "REVERSE_CHARGING";
4347 logtext = "REMOTE_HOLD";
4350 logtext = "REMOTE_RETRIEVAL";
4353 logtext = "CALL_IS_DIVERTING";
4356 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4360 trace_header("NOTIFY", dir);
4361 if (dir == DIRECTION_OUT)
4362 add_trace("to", NULL, "CH(%lu)", port_id);
4363 if (dir == DIRECTION_IN)
4364 add_trace("from", NULL, "CH(%lu)", port_id);
4365 if (param->notifyinfo.notify)
4366 add_trace("indicator", NULL, "%s", logtext);
4367 if (param->notifyinfo.id[0])
4369 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype));
4370 switch(param->notifyinfo.present)
4372 case INFO_PRESENT_RESTRICTED:
4373 add_trace("redir'on", "present", "restricted");
4375 case INFO_PRESENT_ALLOWED:
4376 add_trace("redir'on", "present", "allowed");
4379 add_trace("redir'on", "present", "not available");
4382 if (param->notifyinfo.display[0])
4383 add_trace("display", NULL, "%s", param->notifyinfo.display);
4387 case MESSAGE_INFORMATION:
4388 trace_header("INFORMATION", dir);
4389 if (dir == DIRECTION_OUT)
4390 add_trace("to", NULL, "CH(%lu)", port_id);
4391 if (dir == DIRECTION_IN)
4392 add_trace("from", NULL, "CH(%lu)", port_id);
4393 add_trace("dialing", NULL, "%s", param->information.id);
4397 case MESSAGE_FACILITY:
4398 trace_header("FACILITY", dir);
4399 if (dir == DIRECTION_OUT)
4400 add_trace("to", NULL, "CH(%lu)", port_id);
4401 if (dir == DIRECTION_IN)
4402 add_trace("from", NULL, "CH(%lu)", port_id);
4407 trace_header("TONE", dir);
4408 if (dir == DIRECTION_OUT)
4409 add_trace("to", NULL, "CH(%lu)", port_id);
4410 if (dir == DIRECTION_IN)
4411 add_trace("from", NULL, "CH(%lu)", port_id);
4412 if (param->tone.name[0])
4414 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4415 add_trace("name", NULL, "%s", param->tone.name);
4417 add_trace("off", NULL, NULL);
4421 case MESSAGE_SUSPEND:
4422 case MESSAGE_RESUME:
4423 if (message_type == MESSAGE_SUSPEND)
4424 trace_header("SUSPEND", dir);
4426 trace_header("RESUME", dir);
4427 if (dir == DIRECTION_OUT)
4428 add_trace("to", NULL, "CH(%lu)", port_id);
4429 if (dir == DIRECTION_IN)
4430 add_trace("from", NULL, "CH(%lu)", port_id);
4431 if (param->parkinfo.len)
4432 add_trace("length", NULL, "%d", param->parkinfo.len);
4437 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4441 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4443 struct message *message;
4447 if (!portlist->port_id)
4450 if (!e_connectedmode)
4452 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4453 message->param.disconnectinfo.cause = cause;
4454 message->param.disconnectinfo.location = location;
4456 SCPY(message->param.disconnectinfo.display, display);
4458 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4461 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4463 SCPY(message->param.notifyinfo.display, display);
4465 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4467 message_put(message);
4468 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);