1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 class EndpointAppPBX *apppbx_first = NULL;
18 * EndpointAppPBX constructor
20 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
22 class EndpointAppPBX **apppointer;
24 /* add application to chain */
26 apppointer = &apppbx_first;
28 apppointer = &((*apppointer)->next);
32 memset(&e_ext, 0, sizeof(struct extension));
33 // *************** NOTE: also change value in read_extension() **************
34 e_ext.rights = 4; /* international */
35 e_ext.rx_gain = e_ext.tx_gain = 0;
36 e_state = EPOINT_STATE_IDLE;
37 e_ext.number[0] = '\0';
38 e_extension_interface[0] = '\0';
39 memset(&e_callerinfo, 0, sizeof(struct caller_info));
40 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
41 memset(&e_connectinfo, 0, sizeof(struct connect_info));
42 memset(&e_redirinfo, 0, sizeof(struct redir_info));
43 memset(&e_capainfo, 0, sizeof(struct capa_info));
46 e_ruleset = ruleset_main;
48 e_rule = e_ruleset->rule_first;
53 e_match_to_action = NULL;
55 e_extdialing = e_dialinginfo.id;
59 // e_join_tone[0] = e_hold_tone[0] = '\0';
60 e_join_pattern /*= e_hold_pattern*/ = 0;
63 e_adminid = 0; // will be set, if call was initiated via admin socket
68 e_cbdialing[0] = '\0';
71 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
78 e_password_timeout = 0;
79 e_multipoint_cause = 0;
80 e_multipoint_location = 0;
81 e_dialing_queue[0] = '\0';
83 e_crypt_state = CM_ST_NULL;
84 e_crypt_keyengine_busy = 0;
85 e_crypt_info[0] = '\0';
88 e_tx_state = NOTIFY_STATE_ACTIVE;
89 e_rx_state = NOTIFY_STATE_ACTIVE;
90 e_join_cause = e_join_location = 0;
91 /*********************************
92 *********************************
93 ********* ATTENTION *************
94 *********************************
95 *********************************/
96 /* if you add new values, that must be initialized, also check if they must
97 * be initialized when doing callback
103 * EpointAppPBX destructor
105 EndpointAppPBX::~EndpointAppPBX(void)
107 class EndpointAppPBX *temp, **tempp;
111 tempp = &apppbx_first;
121 FATAL("Endpoint not in endpoint's list.\n");
128 * trace header for application
130 void EndpointAppPBX::trace_header(char *name, int direction)
134 char msgtext[sizeof(_trace.name)];
138 /* init trace with given values */
141 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
145 ea_endpoint->ep_serial,
152 /* set new endpoint state
154 void EndpointAppPBX::new_state(int state)
157 if (e_state != state)
159 trace_header("NEW STATE", DIRECTION_NONE);
160 add_trace("state", "old", "%s", state_name[e_state]);
161 add_trace("state", "new", "%s", state_name[state]);
169 /* release join and port (as specified)
171 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
173 struct port_list *portlist;
174 struct lcr_msg *message;
177 /* message to test call */
178 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
180 /* if a release is pending */
181 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
183 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
184 if (ea_endpoint->ep_join_id)
186 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
187 message->param.disconnectinfo.cause = joincause;
188 message->param.disconnectinfo.location = joinlocation;
189 message_put(message);
190 ea_endpoint->ep_join_id = 0;
194 if (release != RELEASE_PORT_JOINONLY)
197 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
202 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
204 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
205 while((portlist = ea_endpoint->ep_portlist))
207 if (portlist->port_id)
209 SPRINT(cause, "cause_%02x", portcause);
210 set_tone(portlist, cause);
211 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
212 message->param.disconnectinfo.cause = portcause;
213 message->param.disconnectinfo.location = portlocation;
214 message_put(message);
215 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
217 ea_endpoint->free_portlist(portlist);
220 /* if callback is enabled, call back with the given caller id */
223 /* reset some stuff */
224 new_state(EPOINT_STATE_IDLE);
225 memset(&e_connectinfo, 0, sizeof(struct connect_info));
226 memset(&e_redirinfo, 0, sizeof(struct redir_info));
227 e_start = e_stop = 0;
228 e_ruleset = ruleset_main;
230 e_rule = e_ruleset->rule_first;
232 e_action_timeout = 0;
234 e_match_to_action = NULL;
236 e_extdialing = e_dialinginfo.id;
243 e_multipoint_cause = 0;
244 e_multipoint_location = 0;
245 e_dialing_queue[0] = '\0';
247 e_crypt_state = CM_ST_NULL;
248 e_crypt_keyengine_busy = 0;
249 e_crypt_info[0] = '\0';
253 e_tx_state = NOTIFY_STATE_ACTIVE;
254 e_rx_state = NOTIFY_STATE_ACTIVE;
255 e_join_cause = e_join_location = 0;
257 /* the caller info of the callback user */
258 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
259 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
260 /* create dialing by callerinfo */
261 if (e_ext.number[0] && e_extension_interface[0])
263 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
264 /* create callback to the current terminal */
265 SCPY(e_dialinginfo.id, e_ext.number);
266 SCPY(e_dialinginfo.interfaces, e_extension_interface);
267 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
268 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
273 SCPY(e_dialinginfo.id, e_cbto);
276 /* numberrize caller id and use it to dial to the callback */
277 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
279 e_dialinginfo.itype = INFO_ITYPE_ISDN;
280 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
281 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
286 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
287 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
293 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
294 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
296 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");
298 /* caller id is not restricted, so we do nothing */
299 if (*present != INFO_PRESENT_RESTRICTED)
302 /* only extensions are restricted */
306 /* if we enabled anonymouse ignore */
307 if (ext->anon_ignore)
310 /* else we remove the caller id */
314 *ntype = INFO_NTYPE_UNKNOWN;
316 // *screen = INFO_SCREEN_USER;
317 // maybe we should not make voip address anonymous
320 // maybe it's no fraud to present extension id
322 // extension[0] = '\0';
327 /* used display message to display callerid as available */
328 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *extension, char *name)
330 static char display[81];
333 char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
335 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");
344 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
346 /* internal extension's caller id */
347 if (extension[0] && e_ext.display_int)
350 SCAT(display, extension);
353 if (itype == INFO_ITYPE_VBOX)
354 SCAT(display, "(vbox)");
356 SCAT(display, "(int)");
359 /* external caller id */
360 if (!extension[0] && e_ext.display_ext)
366 if (present == INFO_PRESENT_RESTRICTED)
367 SCAT(display, "anonymous");
369 SCAT(display, "unknown");
376 /* display if callerid is anonymouse but available due anon-ignore */
377 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
380 SCAT(display, "unknown");
383 SCAT(display, " anon");
386 /* display if callerid is anonymouse but available due anon-ignore */
387 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
393 if (present == INFO_PRESENT_RESTRICTED)
394 SCAT(display, "anonymous");
396 SCAT(display, "unknown");
401 SCAT(display, " fake");
405 if (name[0] && e_ext.display_name)
407 if (!display[0] && cid[0])
418 * uses the current state to notify activity
420 void EndpointAppPBX::notify_active(void)
422 struct port_list *portlist = ea_endpoint->ep_portlist;
423 struct lcr_msg *message;
428 case NOTIFY_STATE_ACTIVE:
429 /* we are already active, so we don't do anything */
432 case NOTIFY_STATE_SUSPEND:
433 notify = INFO_NOTIFY_USER_RESUMED;
436 set_tone(portlist, NULL);
437 portlist = portlist->next;
439 portlist = ea_endpoint->ep_portlist;
442 case NOTIFY_STATE_HOLD:
443 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
446 set_tone(portlist, NULL);
447 portlist = portlist->next;
449 portlist = ea_endpoint->ep_portlist;
452 case NOTIFY_STATE_CONFERENCE:
453 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
456 set_tone(portlist, NULL);
457 portlist = portlist->next;
459 portlist = ea_endpoint->ep_portlist;
463 PERROR("unknown e_tx_state = %d\n", e_tx_state);
469 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
470 message->param.notifyinfo.notify = notify;
471 message_put(message);
472 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
473 portlist = portlist->next;
479 * keypad functions during call. one example to use this is to put a call on hold or start a conference
481 void EndpointAppPBX::keypad_function(char digit)
484 /* we must be in a call, in order to send messages to the call */
485 if (e_ext.number[0] == '\0')
487 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
493 /* join conference */
495 if (ea_endpoint->ep_join_id == 0)
497 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
500 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
506 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
510 /* crypt key-exchange */
512 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
518 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
523 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
528 /* set tone pattern for port */
529 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
531 struct lcr_msg *message;
536 /* store for suspended processes */
540 if (e_join_pattern /* pattern are provided */
541 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
542 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
543 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
544 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
545 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
546 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
547 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
548 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
549 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
550 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
551 && tone[0] && !!strncmp(tone,"crypt_*",6))
553 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
559 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
560 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
561 SCPY(message->param.tone.name, tone);
562 message_put(message);
563 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
566 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
573 * hunts an mISDNport that is available for an outgoing call
574 * if no ifname was given, any interface that is not an extension
577 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
579 struct interface *interface;
580 struct interface_port *ifport, *ifport_start;
581 struct select_channel *selchannel;
582 struct mISDNport *mISDNport;
585 interface = interface_first;
587 /* first find the given interface or, if not given, one with no extension */
592 /* check for given interface */
595 if (!strcasecmp(interface->name, ifname))
597 /* found explicit interface */
598 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
599 add_trace("interface", NULL, "%s", ifname);
606 if (!interface->extension)
608 /* found non extension */
609 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
610 add_trace("interface", NULL, "%s", interface->name);
616 interface = interface->next;
620 /* see if interface has ports */
621 if (!interface->ifport)
624 trace_header("CHANNEL SELECTION (interface has no active ports, skipping)", DIRECTION_NONE);
625 add_trace("interface", NULL, "%s", interface->name);
627 interface = interface->next;
631 /* select port by algorithm */
632 ifport_start = interface->ifport;
634 if (interface->hunt == HUNT_ROUNDROBIN)
636 while(ifport_start->next && index<interface->hunt_next)
638 ifport_start = ifport_start->next;
641 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
642 add_trace("port", NULL, "%d", ifport_start->portnum);
643 add_trace("position", NULL, "%d", index);
648 ifport = ifport_start;
651 /* see if port is available */
652 if (!ifport->mISDNport)
654 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
655 add_trace("port", NULL, "%d", ifport->portnum);
656 add_trace("position", NULL, "%d", index);
660 mISDNport = ifport->mISDNport;
662 /* see if port is administratively blocked */
665 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
666 add_trace("port", NULL, "%d", ifport->portnum);
667 add_trace("position", NULL, "%d", index);
672 /* see if link is up on PTP*/
673 if (mISDNport->l2hold && !mISDNport->l2link)
675 trace_header("CHANNEL SELECTION (port holds layer 2, but layer 2 is down, skipping)", DIRECTION_NONE);
676 add_trace("port", NULL, "%d", ifport->portnum);
677 add_trace("position", NULL, "%d", index);
682 /* check for channel form selection list */
684 selchannel = ifport->out_channel;
687 switch(selchannel->channel)
689 case CHANNEL_FREE: /* free channel */
690 if (mISDNport->b_reserved >= mISDNport->b_num)
691 break; /* all channel in use or reserverd */
694 while(i < mISDNport->b_num)
696 if (mISDNport->b_port[i] == NULL)
698 *channel = i+1+(i>=15);
699 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
700 add_trace("port", NULL, "%d", ifport->portnum);
701 add_trace("position", NULL, "%d", index);
702 add_trace("channel", NULL, "%d", *channel);
710 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
711 add_trace("port", NULL, "%d", ifport->portnum);
712 add_trace("position", NULL, "%d", index);
716 case CHANNEL_ANY: /* don't ask for channel */
717 if (mISDNport->b_reserved >= mISDNport->b_num)
719 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
720 add_trace("port", NULL, "%d", ifport->portnum);
721 add_trace("position", NULL, "%d", index);
722 add_trace("total", NULL, "%d", mISDNport->b_num);
723 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
725 break; /* all channel in use or reserverd */
727 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
728 add_trace("port", NULL, "%d", ifport->portnum);
729 add_trace("position", NULL, "%d", index);
731 *channel = CHANNEL_ANY;
734 case CHANNEL_NO: /* call waiting */
735 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
736 add_trace("port", NULL, "%d", ifport->portnum);
737 add_trace("position", NULL, "%d", index);
739 *channel = CHANNEL_NO;
743 if (selchannel->channel<1 || selchannel->channel==16)
745 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
746 add_trace("port", NULL, "%d", ifport->portnum);
747 add_trace("position", NULL, "%d", index);
748 add_trace("channel", NULL, "%d", selchannel->channel);
750 break; /* invalid channels */
752 i = selchannel->channel-1-(selchannel->channel>=17);
753 if (i >= mISDNport->b_num)
755 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
756 add_trace("port", NULL, "%d", ifport->portnum);
757 add_trace("position", NULL, "%d", index);
758 add_trace("channel", NULL, "%d", selchannel->channel);
759 add_trace("channels", NULL, "%d", mISDNport->b_num);
761 break; /* channel not in port */
763 if (mISDNport->b_port[i] == NULL)
765 *channel = selchannel->channel;
766 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
767 add_trace("port", NULL, "%d", ifport->portnum);
768 add_trace("position", NULL, "%d", index);
769 add_trace("channel", NULL, "%d", *channel);
776 break; /* found channel */
777 selchannel = selchannel->next;
780 /* if channel was found, return mISDNport and channel */
783 /* setting next port to start next time */
784 if (interface->hunt == HUNT_ROUNDROBIN)
789 interface->hunt_next = index;
795 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
796 add_trace("port", NULL, "%d", ifport->portnum);
797 add_trace("position", NULL, "%d", index);
801 /* go next port, until all ports are checked */
803 ifport = ifport->next;
807 ifport = interface->ifport;
809 if (ifport != ifport_start)
812 return(NULL); /* no port found */
815 /* outgoing setup to port(s)
816 * ports will be created and a setup is sent if everything is ok. otherwhise
817 * the endpoint is destroyed.
819 void EndpointAppPBX::out_setup(void)
821 struct dialing_info dialinginfo;
823 // class pdss1 *pdss1;
824 struct port_list *portlist;
825 struct lcr_msg *message;
827 int cause = CAUSE_RESSOURCEUNAVAIL;
830 struct mISDNport *mISDNport;
833 class EndpointAppPBX *atemp;
834 // char allowed_ports[256];
836 char ifname[sizeof(e_ext.interfaces)],
838 struct port_settings port_settings;
842 /* create settings for creating port */
843 memset(&port_settings, 0, sizeof(port_settings));
845 SCPY(port_settings.tones_dir, e_ext.tones_dir);
847 SCPY(port_settings.tones_dir, options.tones_dir);
848 port_settings.no_seconds = e_ext.no_seconds;
850 /* 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 */
852 /* check what dialinginfo.itype we got */
853 switch(e_dialinginfo.itype)
855 /* *********************** call to extension or vbox */
856 case INFO_ITYPE_ISDN_EXTENSION:
857 /* check if we deny incoming calls when we use an extension */
858 if (e_ext.noknocking)
860 atemp = apppbx_first;
864 if (!strcmp(atemp->e_ext.number, e_ext.number))
870 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
871 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
872 return; /* must exit here */
875 /* FALL THROUGH !!!! */
876 case INFO_ITYPE_VBOX:
877 /* get dialed extension's info */
878 // SCPY(exten, e_dialinginfo.id);
879 // if (strchr(exten, ','))
880 // *strchr(exten, ',') = '\0';
881 // if (!read_extension(&e_ext, exten))
882 if (!read_extension(&e_ext, e_dialinginfo.id))
884 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
885 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
886 return; /* must exit here */
889 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
891 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
896 /* string from unconditional call forward (cfu) */
900 /* present to forwarded party */
901 if (e_ext.anon_ignore && e_callerinfo.id[0])
903 e_callerinfo.present = INFO_PRESENT_ALLOWED;
905 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
909 /* string from busy call forward (cfb) */
913 class EndpointAppPBX *checkapp = apppbx_first;
916 if (checkapp != this) /* any other endpoint except our own */
918 if (!strcmp(checkapp->e_ext.number, e_ext.number))
920 /* present to forwarded party */
921 if (e_ext.anon_ignore && e_callerinfo.id[0])
923 e_callerinfo.present = INFO_PRESENT_ALLOWED;
925 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
929 checkapp = checkapp->next;
933 /* string from no-response call forward (cfnr) */
937 /* when cfnr is done, out_setup() will setup the call */
940 /* present to forwarded party */
941 if (e_ext.anon_ignore && e_callerinfo.id[0])
943 e_callerinfo.present = INFO_PRESENT_ALLOWED;
947 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
949 e_cfnr_release = now + e_ext.cfnr_delay;
950 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
951 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);
955 /* call to all internal interfaces */
956 p = e_ext.interfaces;
957 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
961 while(*p!=',' && *p!='\0')
966 /* found interface */
967 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
968 /* hunt for mISDNport and create Port */
969 mISDNport = hunt_port(ifname, &channel);
972 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
973 add_trace("interface", NULL, "%s", ifname);
977 /* creating INTERNAL port */
978 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
979 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force);
981 FATAL("No memory for DSS1 Port instance\n");
982 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
983 memset(&dialinginfo, 0, sizeof(dialinginfo));
984 SCPY(dialinginfo.id, e_dialinginfo.id);
985 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
986 dialinginfo.ntype = e_dialinginfo.ntype;
987 /* create port_list relation */
988 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
991 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
993 goto check_anycall_intern;
996 if (e_callerinfo.id[0] && e_ext.display_name)
998 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1000 SCPY(e_callerinfo.name, dirname);
1002 // dss1 = (class Pdss1 *)port;
1004 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1005 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1006 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1007 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1008 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1009 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1010 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1011 //terminal if (e_dialinginfo.id)
1012 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1013 /* handle restricted caller ids */
1014 apply_callerid_restriction(&e_ext, 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);
1015 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1016 /* display callerid if desired for extension */
1017 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));
1018 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1019 /* use cnip, if enabld */
1020 // if (!e_ext.centrex)
1021 // message->param.setup.callerinfo.name[0] = '\0';
1022 /* screen clip if prefix is required */
1023 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1025 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1026 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
1027 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1029 /* use internal caller id */
1030 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1032 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1033 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1035 message_put(message);
1036 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1040 /* string from parallel call forward (cfp) */
1044 if (e_ext.anon_ignore && e_callerinfo.id[0])
1046 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1050 vbox_only: /* entry point for answering machine only */
1051 cfu_only: /* entry point for cfu */
1052 cfb_only: /* entry point for cfb */
1053 cfnr_only: /* entry point for cfnr */
1054 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1059 /* only if vbox should be dialed, and terminal is given */
1060 if (!strcmp(p, "vbox") && e_ext.number[0])
1062 /* go to the end of p */
1065 /* answering vbox call */
1066 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1068 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1069 FATAL("No memory for VBOX Port instance\n");
1070 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1071 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1075 while(*p!=',' && *p!='\0')
1080 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1081 /* hunt for mISDNport and create Port */
1082 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1085 /* creating EXTERNAL port*/
1086 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1087 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)))
1088 FATAL("No memory for DSS1 Port instance\n");
1089 earlyb = mISDNport->earlyb;
1093 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1094 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1100 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1101 goto check_anycall_intern;
1103 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1104 memset(&dialinginfo, 0, sizeof(dialinginfo));
1105 SCPY(dialinginfo.id, cfp);
1106 dialinginfo.itype = INFO_ITYPE_ISDN;
1107 dialinginfo.ntype = e_dialinginfo.ntype;
1108 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1111 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1113 goto check_anycall_intern;
1115 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1116 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1117 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1118 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1119 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1120 /* if clip is hidden */
1121 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1123 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1124 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1125 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1126 message->param.setup.callerinfo.present = e_ext.callerid_present;
1128 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1129 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1130 //terminal if (e_dialinginfo.id)
1131 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1132 /* handle restricted caller ids */
1133 apply_callerid_restriction(&e_ext, 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);
1134 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1135 /* display callerid if desired for extension */
1136 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));
1137 message_put(message);
1138 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1142 check_anycall_intern:
1143 /* now we have all ports created */
1146 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1148 if (!ea_endpoint->ep_join_id)
1150 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1151 return; /* must exit here */
1155 /* *********************** external call */
1157 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1158 /* call to extenal interfaces */
1159 p = e_dialinginfo.id;
1163 while(*p!=',' && *p!='\0')
1164 SCCAT(number, *p++);
1168 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");
1169 /* hunt for mISDNport and create Port */
1170 /* hunt for mISDNport and create Port */
1171 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1174 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1175 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1177 goto check_anycall_extern;
1179 /* creating EXTERNAL port*/
1180 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1181 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)))
1182 FATAL("No memory for DSS1 Port instance\n");
1183 earlyb = mISDNport->earlyb;
1184 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1185 memset(&dialinginfo, 0, sizeof(dialinginfo));
1186 SCPY(dialinginfo.id, number);
1187 dialinginfo.itype = INFO_ITYPE_ISDN;
1188 dialinginfo.ntype = e_dialinginfo.ntype;
1189 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1192 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1194 goto check_anycall_extern;
1196 // dss1 = (class Pdss1 *)port;
1197 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1198 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1199 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1200 SCPY(message->param.setup.dialinginfo.id, number);
1201 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1202 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1203 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1204 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1205 //terminal if (e_dialinginfo.id)
1206 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1207 /* handle restricted caller ids */
1208 apply_callerid_restriction(&e_ext, 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);
1209 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1210 /* display callerid if desired for extension */
1211 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));
1212 message_put(message);
1213 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1217 check_anycall_extern:
1218 /* now we have all ports created */
1221 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1223 if (!ea_endpoint->ep_join_id)
1225 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1226 return; /* must exit here */
1234 /* handler for endpoint
1238 int EndpointAppPBX::handler(void)
1240 if (e_crypt_state!=CM_ST_NULL)
1245 /* process answering machine (play) handling */
1248 if (e_action->index == ACTION_VBOX_PLAY)
1251 /* process action timeout */
1252 if (e_action_timeout)
1253 if (now_d >= e_action_timeout)
1255 if (e_state!=EPOINT_STATE_CONNECT)
1258 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1259 e_multipoint_cause = 0;
1260 e_multipoint_location = 0;
1261 new_state(EPOINT_STATE_IN_OVERLAP);
1264 return(1); /* we must exit, because our endpoint might be gone */
1266 e_action_timeout = 0;
1269 /* process action timeout */
1270 if (e_match_timeout)
1271 if (now_d >= e_match_timeout)
1274 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1276 return(1); /* we must exit, because our endpoint might be gone */
1281 /* process redialing (epoint redials to port) */
1284 if (now_d >= e_redial)
1287 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1289 new_state(EPOINT_STATE_OUT_SETUP);
1290 /* call special setup routine */
1297 /* process powerdialing (epoint redials to epoint) */
1298 if (e_powerdialing > 0)
1300 if (now_d >= e_powerdialing)
1302 e_powerdialing = -1; /* leave power dialing on */
1303 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1306 e_ruleset = ruleset_main;
1308 e_rule = e_ruleset->rule_first;
1310 new_state(EPOINT_STATE_IN_OVERLAP);
1316 /* process call forward no response */
1319 struct port_list *portlist;
1320 struct lcr_msg *message;
1322 if (now >= e_cfnr_release)
1324 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1327 /* release all ports */
1328 while((portlist = ea_endpoint->ep_portlist))
1330 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1331 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1332 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1333 message_put(message);
1334 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1335 ea_endpoint->free_portlist(portlist);
1338 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1339 message->param.audiopath = CHANNEL_STATE_HOLD;
1340 message_put(message);
1341 /* indicate no patterns */
1342 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1343 message_put(message);
1344 /* set setup state, since we have no response from the new join */
1345 new_state(EPOINT_STATE_OUT_SETUP);
1350 if (now >= e_cfnr_call)
1352 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1358 /* handle connection to user */
1359 if (e_state == EPOINT_STATE_IDLE)
1361 /* epoint is idle, check callback */
1363 if (now_d >= e_callback)
1365 e_callback = 0; /* done with callback */
1366 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1367 new_state(EPOINT_STATE_OUT_SETUP);
1373 /* check for password timeout */
1375 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1377 struct port_list *portlist;
1379 if (now >= e_password_timeout)
1381 e_ruleset = ruleset_main;
1383 e_rule = e_ruleset->rule_first;
1385 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1386 trace_header("PASSWORD timeout", DIRECTION_NONE);
1388 e_connectedmode = 0;
1390 new_state(EPOINT_STATE_OUT_DISCONNECT);
1391 portlist = ea_endpoint->ep_portlist;
1394 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1395 set_tone(portlist, "cause_10");
1405 /* doing a hookflash */
1406 void EndpointAppPBX::hookflash(void)
1410 /* be sure that we are active */
1412 e_tx_state = NOTIFY_STATE_ACTIVE;
1414 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1416 if (ea_endpoint->ep_use > 1)
1418 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1421 /* dialtone after pressing the hash key */
1422 process_hangup(e_join_cause, e_join_location);
1423 e_multipoint_cause = 0;
1424 e_multipoint_location = 0;
1425 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1428 port->set_echotest(0);
1430 if (ea_endpoint->ep_join_id)
1432 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1434 e_ruleset = ruleset_main;
1436 e_rule = e_ruleset->rule_first;
1438 new_state(EPOINT_STATE_IN_OVERLAP);
1439 e_connectedmode = 1;
1440 SCPY(e_dialinginfo.id, e_ext.prefix);
1441 e_extdialing = e_dialinginfo.id;
1443 if (e_dialinginfo.id[0])
1445 set_tone(ea_endpoint->ep_portlist, "dialing");
1449 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1456 /* messages from port
1458 /* port MESSAGE_SETUP */
1459 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1461 struct lcr_msg *message;
1463 int writeext; /* flags need to write extension after modification */
1465 struct interface *interface;
1467 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1469 portlist->port_type = param->setup.port_type;
1470 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1471 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1472 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1473 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1474 e_dtmf = param->setup.dtmf;
1475 /* screen incoming caller id */
1476 interface = interface_first;
1479 if (!strcmp(e_callerinfo.interface, interface->name))
1483 interface = interface->next;
1486 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1488 /* process extension */
1489 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1491 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1492 /* port makes call from extension */
1493 SCPY(e_callerinfo.extension, e_callerinfo.id);
1494 SCPY(e_ext.number, e_callerinfo.extension);
1495 SCPY(e_extension_interface, e_callerinfo.interface);
1498 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1501 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1503 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1505 /* get extension's info about caller */
1506 if (!read_extension(&e_ext, e_ext.number))
1508 /* extension doesn't exist */
1509 trace_header("EXTENSION (not created)", DIRECTION_IN);
1510 add_trace("extension", NULL, "%s", e_ext.number);
1512 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1513 new_state(EPOINT_STATE_OUT_DISCONNECT);
1514 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1515 e_ext.number[0] = '\0'; /* no terminal */
1520 /* put prefix (next) in front of e_dialinginfo.id */
1523 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1524 SCPY(e_dialinginfo.id, buffer);
1525 e_ext.next[0] = '\0';
1527 } else if (e_ext.prefix[0])
1529 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1530 SCPY(e_dialinginfo.id, buffer);
1533 /* screen caller id by extension's config */
1534 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1536 SCPY(e_callerinfo.name, e_ext.name);
1537 /* use caller id (or if exist: id_next_call) for this call */
1538 if (e_ext.id_next_call_present >= 0)
1540 SCPY(e_callerinfo.id, e_ext.id_next_call);
1541 /* if we restrict the pesentation */
1542 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1543 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1544 else e_callerinfo.present = e_ext.id_next_call_present;
1545 e_callerinfo.ntype = e_ext.id_next_call_type;
1546 e_ext.id_next_call_present = -1;
1550 SCPY(e_callerinfo.id, e_ext.callerid);
1551 /* if we restrict the pesentation */
1552 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1553 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1554 else e_callerinfo.present = e_ext.callerid_present;
1555 e_callerinfo.ntype = e_ext.callerid_type;
1558 /* extension is written */
1560 write_extension(&e_ext, e_ext.number);
1562 /* set volume of rx and tx */
1563 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1564 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
1566 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1567 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1568 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1569 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1570 message_put(message);
1573 /* start recording if enabled */
1574 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1576 /* check if we are a terminal */
1577 if (e_ext.number[0] == '\0')
1578 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1581 port = find_port_id(portlist->port_id);
1583 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1588 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1589 /* no terminal identification */
1590 e_ext.number[0] = '\0';
1591 e_extension_interface[0] = '\0';
1592 memset(&e_ext, 0, sizeof(e_ext));
1593 e_ext.rights = 4; /* right to dial internat */
1597 e_ruleset = ruleset_main;
1599 e_rule = e_ruleset->rule_first;
1601 e_extdialing = e_dialinginfo.id;
1602 new_state(EPOINT_STATE_IN_SETUP);
1603 if (e_dialinginfo.id[0])
1605 set_tone(portlist, "dialing");
1608 if (e_ext.number[0])
1609 set_tone(portlist, "dialpbx");
1611 set_tone(portlist, "dialtone");
1614 if (e_state == EPOINT_STATE_IN_SETUP)
1616 /* request MORE info, if not already at higher state */
1617 new_state(EPOINT_STATE_IN_OVERLAP);
1618 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1619 message_put(message);
1620 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1624 /* port MESSAGE_INFORMATION */
1625 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1627 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1631 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1634 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1639 /* if vbox_play is done, the information are just used as they come */
1641 if (e_action->index == ACTION_VBOX_PLAY)
1643 /* concat dialing string */
1644 SCAT(e_dialinginfo.id, param->information.id);
1649 /* keypad when disconnect but in connected mode */
1650 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1652 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1653 /* processing keypad function */
1654 if (param->information.id[0] == '0')
1661 /* keypad when connected */
1662 if (e_state == EPOINT_STATE_CONNECT)
1666 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1667 /* processing keypad function */
1668 if (param->information.id[0] == '0')
1672 if (param->information.id[0])
1673 keypad_function(param->information.id[0]);
1676 if (e_ext.number[0])
1677 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1679 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1684 if (e_state != EPOINT_STATE_IN_OVERLAP)
1686 if (e_ext.number[0])
1687 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1689 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1693 if (!param->information.id[0])
1695 if (e_dialinginfo.id[0]=='\0' && !e_action)
1697 set_tone(portlist, "dialing");
1700 if (e_action->index==ACTION_OUTDIAL
1701 || e_action->index==ACTION_EXTERNAL)
1704 set_tone(portlist, "dialing");
1705 else if (!e_extdialing[0])
1706 set_tone(portlist, "dialing");
1708 /* concat dialing string */
1709 SCAT(e_dialinginfo.id, param->information.id);
1713 /* port MESSAGE_DTMF */
1714 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1716 /* only if dtmf detection is enabled */
1719 trace_header("DTMF (disabled)", DIRECTION_IN);
1723 trace_header("DTMF", DIRECTION_IN);
1724 add_trace("digit", NULL, "%c", param->dtmf);
1728 NOTE: vbox is now handled due to overlap state
1729 /* if vbox_play is done, the dtmf digits are just used as they come */
1731 if (e_action->index == ACTION_VBOX_PLAY)
1733 /* concat dialing string */
1734 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1736 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1737 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1740 /* continue to process *X# sequences */
1744 /* check for *X# sequence */
1745 if (e_state == EPOINT_STATE_CONNECT)
1747 if (e_dtmf_time+3 < now)
1749 /* the last digit was too far in the past to be a sequence */
1750 if (param->dtmf == '*')
1751 /* only start is allowed in the sequence */
1757 /* we have a sequence of digits, see what we got */
1758 if (param->dtmf == '*')
1760 else if (param->dtmf>='0' && param->dtmf<='9')
1762 /* we need to have a star before we receive the digit of the sequence */
1763 if (e_dtmf_last == '*')
1764 e_dtmf_last = param->dtmf;
1765 } else if (param->dtmf == '#')
1768 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1770 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1771 if (e_dtmf_last == '0')
1776 /* processing keypad function */
1778 keypad_function(e_dtmf_last);
1784 /* set last time of dtmf */
1789 /* check for ## hookflash during dialing */
1791 if (e_action->index==ACTION_PASSWORD
1792 || e_action->index==ACTION_PASSWORD_WRITE)
1794 if (param->dtmf=='#') /* current digit is '#' */
1796 if (e_state==EPOINT_STATE_IN_DISCONNECT
1797 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1814 /* dialing using dtmf digit */
1815 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1817 if (e_dialinginfo.id[0]=='\0' && !e_action)
1819 set_tone(portlist, "dialing");
1821 /* concat dialing string */
1822 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1824 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1825 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1831 /* port MESSAGE_CRYPT */
1832 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1834 /* send crypt response to cryptman */
1835 if (param->crypt.type == CR_MESSAGE_IND)
1836 cryptman_msg2man(param->crypt.data, param->crypt.len);
1838 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1841 /* port MESSAGE_OVERLAP */
1842 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1844 struct lcr_msg *message;
1846 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1848 /* signal to call tool */
1849 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1851 if (e_dialing_queue[0] && portlist)
1853 /* send what we have not dialed yet, because we had no setup complete */
1854 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1855 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1856 SCPY(message->param.information.id, e_dialing_queue);
1857 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1858 message_put(message);
1859 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1860 e_dialing_queue[0] = '\0';
1862 /* check if pattern is available */
1863 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
1865 /* indicate patterns */
1866 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1867 message_put(message);
1869 /* connect audio, if not already */
1870 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1871 message->param.audiopath = CHANNEL_STATE_CONNECT;
1872 message_put(message);
1875 /* indicate no patterns */
1876 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1877 message_put(message);
1879 /* disconnect audio, if not already */
1880 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1881 message->param.audiopath = CHANNEL_STATE_HOLD;
1882 message_put(message);
1884 new_state(EPOINT_STATE_OUT_OVERLAP);
1885 /* if we are in a join */
1886 if (ea_endpoint->ep_join_id)
1888 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1889 memcpy(&message->param, param, sizeof(union parameter));
1890 message_put(message);
1894 /* port MESSAGE_PROCEEDING */
1895 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1897 struct lcr_msg *message;
1899 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1901 /* signal to call tool */
1902 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1904 e_state = EPOINT_STATE_OUT_PROCEEDING;
1905 /* check if pattern is availatle */
1906 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1908 /* indicate patterns */
1909 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1910 message_put(message);
1912 /* connect audio, if not already */
1913 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1914 message->param.audiopath = CHANNEL_STATE_CONNECT;
1915 message_put(message);
1918 /* indicate no patterns */
1919 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1920 message_put(message);
1922 /* disconnect audio, if not already */
1923 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1924 message->param.audiopath = CHANNEL_STATE_HOLD;
1925 message_put(message);
1927 /* if we are in a call */
1928 if (ea_endpoint->ep_join_id)
1930 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1931 memcpy(&message->param, param, sizeof(union parameter));
1932 message_put(message);
1936 /* port MESSAGE_ALERTING */
1937 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1939 struct lcr_msg *message;
1941 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1943 /* signal to call tool */
1944 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1946 new_state(EPOINT_STATE_OUT_ALERTING);
1947 /* check if pattern is available */
1948 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1950 /* indicate patterns */
1951 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1952 message_put(message);
1954 /* connect audio, if not already */
1955 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1956 message->param.audiopath = CHANNEL_STATE_CONNECT;
1957 message_put(message);
1960 /* indicate no patterns */
1961 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1962 message_put(message);
1964 /* disconnect audio, if not already */
1965 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1966 message->param.audiopath = CHANNEL_STATE_HOLD;
1967 message_put(message);
1969 /* if we are in a call */
1970 if (ea_endpoint->ep_join_id)
1972 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1973 memcpy(&message->param, param, sizeof(union parameter));
1974 message_put(message);
1978 /* port MESSAGE_CONNECT */
1979 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1981 struct lcr_msg *message;
1983 unsigned long port_id = portlist->port_id;
1984 struct port_list *tportlist;
1986 struct interface *interface;
1988 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1990 /* signal to call tool */
1991 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
1993 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
1994 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
1995 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
1997 tportlist = ea_endpoint->ep_portlist;
1998 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
1999 tportlist = tportlist->next;
2000 if (tportlist->port_id == port_id)
2001 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2002 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2003 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2004 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2005 message_put(message);
2006 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2007 ea_endpoint->free_portlist(tportlist);
2009 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2013 /* screen incoming connected id */
2014 interface = interface_first;
2017 if (!strcmp(e_connectinfo.interface, interface->name))
2021 interface = interface->next;
2024 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2026 /* screen connected name */
2028 SCPY(e_connectinfo.name, e_ext.name);
2030 /* add internal id to colp */
2031 SCPY(e_connectinfo.extension, e_ext.number);
2033 /* we store the connected port number */
2034 SCPY(e_extension_interface, e_connectinfo.interface);
2036 /* for internal and am calls, we get the extension's id */
2037 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2039 SCPY(e_connectinfo.id, e_ext.callerid);
2040 SCPY(e_connectinfo.extension, e_ext.number);
2041 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2042 e_connectinfo.ntype = e_ext.callerid_type;
2043 e_connectinfo.present = e_ext.callerid_present;
2045 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2047 e_connectinfo.itype = INFO_ITYPE_VBOX;
2048 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2051 new_state(EPOINT_STATE_CONNECT);
2053 /* set volume of rx and tx */
2054 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2056 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2057 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2058 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2059 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2060 message_put(message);
2063 e_cfnr_call = e_cfnr_release = 0;
2064 if (e_ext.number[0])
2065 e_dtmf = 1; /* allow dtmf */
2068 /* other calls with no caller id (or not available for the extension) and force colp */
2069 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2071 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2072 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2074 port = find_port_id(portlist->port_id);
2077 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
2078 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2083 /* send connect to join */
2084 if (ea_endpoint->ep_join_id)
2086 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2087 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2088 message_put(message);
2090 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2091 message->param.audiopath = CHANNEL_STATE_CONNECT;
2092 message_put(message);
2093 } else if (!e_adminid)
2096 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2097 SCPY(e_ext.number, e_cbcaller);
2098 new_state(EPOINT_STATE_IN_OVERLAP);
2099 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2101 /* get extension's info about terminal */
2102 if (!read_extension(&e_ext, e_ext.number))
2104 /* extension doesn't exist */
2105 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2106 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2107 new_state(EPOINT_STATE_OUT_DISCONNECT);
2108 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2112 /* put prefix in front of e_cbdialing */
2113 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2114 SCPY(e_dialinginfo.id, buffer);
2115 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2116 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2118 /* use caller id (or if exist: id_next_call) for this call */
2119 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2120 SCPY(e_callerinfo.extension, e_ext.number);
2121 if (e_ext.id_next_call_present >= 0)
2123 SCPY(e_callerinfo.id, e_ext.id_next_call);
2124 e_callerinfo.present = e_ext.id_next_call_present;
2125 e_callerinfo.ntype = e_ext.id_next_call_type;
2126 e_ext.id_next_call_present = -1;
2127 /* extension is written */
2128 write_extension(&e_ext, e_ext.number);
2131 SCPY(e_callerinfo.id, e_ext.callerid);
2132 e_callerinfo.present = e_ext.callerid_present;
2133 e_callerinfo.ntype = e_ext.callerid_type;
2136 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2139 /* check if caller id is NOT authenticated */
2140 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2142 /* make call state to enter password */
2143 new_state(EPOINT_STATE_IN_OVERLAP);
2144 e_action = &action_password_write;
2145 e_match_timeout = 0;
2146 e_match_to_action = NULL;
2147 e_dialinginfo.id[0] = '\0';
2148 e_extdialing = strchr(e_dialinginfo.id, '\0');
2149 e_password_timeout = now+20;
2153 /* incoming call (callback) */
2154 e_ruleset = ruleset_main;
2156 e_rule = e_ruleset->rule_first;
2158 e_extdialing = e_dialinginfo.id;
2159 if (e_dialinginfo.id[0])
2161 set_tone(portlist, "dialing");
2165 set_tone(portlist, "dialpbx");
2168 } else /* testcall */
2170 set_tone(portlist, "hold");
2173 /* start recording if enabled, not when answering machine answers */
2174 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))
2176 /* check if we are a terminal */
2177 if (e_ext.number[0] == '\0')
2178 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2181 port = find_port_id(portlist->port_id);
2183 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2188 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2189 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2191 struct lcr_msg *message;
2193 unsigned long port_id = portlist->port_id;
2197 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2199 /* signal to call tool */
2200 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2202 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2203 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2205 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2210 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);
2211 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2212 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2214 /* check if we have more than one portlist relation and we just ignore the disconnect */
2215 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2217 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2218 portlist = ea_endpoint->ep_portlist;
2221 if (portlist->port_id == port_id)
2223 portlist = portlist->next;
2226 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2227 if (message_type != MESSAGE_RELEASE)
2229 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2230 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2231 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2232 message_put(message);
2233 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2235 ea_endpoint->free_portlist(portlist);
2236 return; /* one relation removed */
2238 if (e_state == EPOINT_STATE_CONNECT)
2240 /* use cause from port after connect */
2241 cause = param->disconnectinfo.cause;
2242 location = param->disconnectinfo.location;
2245 /* use multipoint cause if no connect yet */
2246 if (e_multipoint_cause)
2248 cause = e_multipoint_cause;
2249 location = e_multipoint_location;
2252 cause = CAUSE_NOUSER;
2253 location = LOCATION_PRIVATE_LOCAL;
2257 e_cfnr_call = e_cfnr_release = 0;
2259 /* process hangup */
2260 process_hangup(e_join_cause, e_join_location);
2261 e_multipoint_cause = 0;
2262 e_multipoint_location = 0;
2264 if (message_type == MESSAGE_DISCONNECT)
2266 /* tone to disconnected end */
2267 SPRINT(buffer, "cause_%02x", cause);
2268 if (ea_endpoint->ep_portlist)
2269 set_tone(ea_endpoint->ep_portlist, buffer);
2271 new_state(EPOINT_STATE_IN_DISCONNECT);
2274 if (ea_endpoint->ep_join_id)
2276 int haspatterns = 0;
2277 /* check if pattern is available */
2278 if (ea_endpoint->ep_portlist)
2279 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2280 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
2281 && message_type != MESSAGE_RELEASE) // if we release, we are done
2285 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2286 /* indicate patterns */
2287 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2288 message_put(message);
2289 /* connect audio, if not already */
2290 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2291 message->param.audiopath = CHANNEL_STATE_CONNECT;
2292 message_put(message);
2293 /* send disconnect */
2294 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2295 memcpy(&message->param, param, sizeof(union parameter));
2296 message_put(message);
2297 /* disable encryption if disconnected */
2298 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2300 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2304 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2307 if (message_type == MESSAGE_RELEASE)
2308 ea_endpoint->free_portlist(portlist);
2309 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2310 return; /* must exit here */
2313 /* port MESSAGE_TIMEOUT */
2314 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2318 trace_header("TIMEOUT", DIRECTION_IN);
2319 message_type = MESSAGE_DISCONNECT;
2320 switch (param->state)
2322 case PORT_STATE_OUT_SETUP:
2323 case PORT_STATE_OUT_OVERLAP:
2324 add_trace("state", NULL, "outgoing setup/dialing");
2326 /* no user responding */
2327 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2328 return; /* must exit here */
2330 case PORT_STATE_IN_SETUP:
2331 case PORT_STATE_IN_OVERLAP:
2332 add_trace("state", NULL, "incoming setup/dialing");
2333 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2334 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2337 case PORT_STATE_OUT_PROCEEDING:
2338 add_trace("state", NULL, "outgoing proceeding");
2340 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2341 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2342 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2343 return; /* must exit here */
2345 case PORT_STATE_IN_PROCEEDING:
2346 add_trace("state", NULL, "incoming proceeding");
2347 param->disconnectinfo.cause = CAUSE_NOUSER;
2348 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2351 case PORT_STATE_OUT_ALERTING:
2352 add_trace("state", NULL, "outgoing alerting");
2354 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2355 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2356 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2357 return; /* must exit here */
2359 case PORT_STATE_CONNECT:
2360 add_trace("state", NULL, "connect");
2362 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2363 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2364 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2365 return; /* must exit here */
2367 case PORT_STATE_IN_ALERTING:
2368 add_trace("state", NULL, "incoming alerting");
2369 param->disconnectinfo.cause = CAUSE_NOANSWER;
2370 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2373 case PORT_STATE_IN_DISCONNECT:
2374 case PORT_STATE_OUT_DISCONNECT:
2375 add_trace("state", NULL, "disconnect");
2377 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2378 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2379 return; /* must exit here */
2382 param->disconnectinfo.cause = 31; /* normal unspecified */
2383 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2386 /* release call, disconnect isdn */
2388 new_state(EPOINT_STATE_OUT_DISCONNECT);
2389 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2390 SCPY(e_tone, cause);
2393 set_tone(portlist, cause);
2394 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2395 portlist = portlist->next;
2397 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2400 /* port MESSAGE_NOTIFY */
2401 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2403 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2405 struct lcr_msg *message;
2409 /* signal to call tool */
2410 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype, options.national, options.international), 0, 0, param->notifyinfo.notify);
2411 if (param->notifyinfo.notify)
2413 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2416 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2417 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2419 case INFO_NOTIFY_REMOTE_HOLD:
2420 case INFO_NOTIFY_USER_SUSPENDED:
2421 /* tell call about it */
2422 if (ea_endpoint->ep_join_id)
2424 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2425 message->param.audiopath = CHANNEL_STATE_HOLD;
2426 message_put(message);
2430 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2431 case INFO_NOTIFY_USER_RESUMED:
2432 /* set volume of rx and tx */
2433 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2434 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2437 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2438 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2439 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2440 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2441 message_put(message);
2443 /* set current tone */
2445 set_tone(portlist, e_tone);
2446 /* tell call about it */
2447 if (ea_endpoint->ep_join_id)
2449 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2450 message->param.audiopath = CHANNEL_STATE_CONNECT;
2451 message_put(message);
2456 /* get name of notify */
2457 switch(param->notifyinfo.notify)
2463 logtext = "USER_SUSPENDED";
2466 logtext = "BEARER_SERVICE_CHANGED";
2469 logtext = "USER_RESUMED";
2472 logtext = "CONFERENCE_ESTABLISHED";
2475 logtext = "CONFERENCE_DISCONNECTED";
2478 logtext = "OTHER_PARTY_ADDED";
2481 logtext = "ISOLATED";
2484 logtext = "REATTACHED";
2487 logtext = "OTHER_PARTY_ISOLATED";
2490 logtext = "OTHER_PARTY_REATTACHED";
2493 logtext = "OTHER_PARTY_SPLIT";
2496 logtext = "OTHER_PARTY_DISCONNECTED";
2499 logtext = "CONFERENCE_FLOATING";
2502 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2505 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2508 logtext = "CALL_IS_A_WAITING_CALL";
2511 logtext = "DIVERSION_ACTIVATED";
2514 logtext = "RESERVED_CT_1";
2517 logtext = "RESERVED_CT_2";
2520 logtext = "REVERSE_CHARGING";
2523 logtext = "REMOTE_HOLD";
2526 logtext = "REMOTE_RETRIEVAL";
2529 logtext = "CALL_IS_DIVERTING";
2532 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2537 /* notify call if available */
2538 if (ea_endpoint->ep_join_id)
2540 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2541 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2542 message_put(message);
2547 /* port MESSAGE_FACILITY */
2548 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2550 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2552 struct lcr_msg *message;
2554 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2555 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2556 message_put(message);
2559 /* port MESSAGE_SUSPEND */
2560 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2561 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2563 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2565 /* epoint is now parked */
2566 ea_endpoint->ep_park = 1;
2567 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2568 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2570 /* remove port relation */
2571 ea_endpoint->free_portlist(portlist);
2574 /* port MESSAGE_RESUME */
2575 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2576 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2578 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2580 /* epoint is now resumed */
2581 ea_endpoint->ep_park = 0;
2586 /* port sends message to the endpoint
2588 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2590 struct port_list *portlist;
2591 struct lcr_msg *message;
2593 portlist = ea_endpoint->ep_portlist;
2596 if (port_id == portlist->port_id)
2598 portlist = portlist->next;
2602 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);
2606 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2607 switch(message_type)
2609 case MESSAGE_DATA: /* data from port */
2610 /* check if there is a call */
2611 if (!ea_endpoint->ep_join_id)
2613 /* continue if only one portlist */
2614 if (ea_endpoint->ep_portlist->next != NULL)
2616 /* forward message */
2617 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2620 case MESSAGE_TONE_EOF: /* tone is end of file */
2621 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2624 if (e_action->index == ACTION_VBOX_PLAY)
2628 if (e_action->index == ACTION_EFI)
2635 case MESSAGE_TONE_COUNTER: /* counter info received */
2636 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);
2638 if (e_action->index == ACTION_VBOX_PLAY)
2640 e_vbox_counter = param->counter.current;
2641 if (param->counter.max >= 0)
2642 e_vbox_counter_max = param->counter.max;
2646 /* PORT sends SETUP message */
2648 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);
2649 if (e_state!=EPOINT_STATE_IDLE)
2651 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2654 port_setup(portlist, message_type, param);
2657 /* PORT sends INFORMATION message */
2658 case MESSAGE_INFORMATION: /* additional digits received */
2659 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);
2660 port_information(portlist, message_type, param);
2663 /* PORT sends FACILITY message */
2664 case MESSAGE_FACILITY:
2665 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2666 port_facility(portlist, message_type, param);
2669 /* PORT sends DTMF message */
2670 case MESSAGE_DTMF: /* dtmf digits received */
2671 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);
2672 port_dtmf(portlist, message_type, param);
2675 /* PORT sends CRYPT message */
2676 case MESSAGE_CRYPT: /* crypt response received */
2677 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2678 port_crypt(portlist, message_type, param);
2681 /* PORT sends MORE message */
2682 case MESSAGE_OVERLAP:
2683 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);
2684 if (e_state != EPOINT_STATE_OUT_SETUP)
2686 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);
2689 port_overlap(portlist, message_type, param);
2692 /* PORT sends PROCEEDING message */
2693 case MESSAGE_PROCEEDING: /* port is proceeding */
2694 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);
2695 if (e_state!=EPOINT_STATE_OUT_SETUP
2696 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2698 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);
2701 port_proceeding(portlist, message_type, param);
2704 /* PORT sends ALERTING message */
2705 case MESSAGE_ALERTING:
2706 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);
2707 if (e_state!=EPOINT_STATE_OUT_SETUP
2708 && e_state!=EPOINT_STATE_OUT_OVERLAP
2709 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2711 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);
2714 port_alerting(portlist, message_type, param);
2717 /* PORT sends CONNECT message */
2718 case MESSAGE_CONNECT:
2719 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);
2720 if (e_state!=EPOINT_STATE_OUT_SETUP
2721 && e_state!=EPOINT_STATE_OUT_OVERLAP
2722 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2723 && e_state!=EPOINT_STATE_OUT_ALERTING)
2725 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2728 port_connect(portlist, message_type, param);
2731 /* PORT sends DISCONNECT message */
2732 case MESSAGE_DISCONNECT: /* port is disconnected */
2733 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);
2734 port_disconnect_release(portlist, message_type, param);
2737 /* PORT sends a RELEASE message */
2738 case MESSAGE_RELEASE: /* port releases */
2739 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);
2740 /* portlist is release at port_disconnect_release, thanx Paul */
2741 port_disconnect_release(portlist, message_type, param);
2744 /* PORT sends a TIMEOUT message */
2745 case MESSAGE_TIMEOUT:
2746 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);
2747 port_timeout(portlist, message_type, param);
2748 break; /* release */
2750 /* PORT sends a NOTIFY message */
2751 case MESSAGE_NOTIFY:
2752 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);
2753 port_notify(portlist, message_type, param);
2756 /* PORT sends a SUSPEND message */
2757 case MESSAGE_SUSPEND:
2758 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);
2759 port_suspend(portlist, message_type, param);
2760 break; /* suspend */
2762 /* PORT sends a RESUME message */
2763 case MESSAGE_RESUME:
2764 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);
2765 port_resume(portlist, message_type, param);
2769 /* port assigns bchannel */
2770 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2771 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel message %d from port.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
2772 /* only one port is expected to be connected to bchannel */
2773 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2774 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2780 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);
2783 /* Note: this endpoint may be destroyed, so we MUST return */
2787 /* messages from join
2789 /* join MESSAGE_CRYPT */
2790 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2792 switch(param->crypt.type)
2794 /* message from remote port to "crypt manager" */
2795 case CU_ACTK_REQ: /* activate key-exchange */
2796 case CU_ACTS_REQ: /* activate shared key */
2797 case CU_DACT_REQ: /* deactivate */
2798 case CU_INFO_REQ: /* request last info message */
2799 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2802 /* message from "crypt manager" to user */
2803 case CU_ACTK_CONF: /* key-echange done */
2804 case CU_ACTS_CONF: /* shared key done */
2805 case CU_DACT_CONF: /* deactivated */
2806 case CU_DACT_IND: /* deactivated */
2807 case CU_ERROR_IND: /* receive error message */
2808 case CU_INFO_IND: /* receive info message */
2809 case CU_INFO_CONF: /* receive info message */
2810 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2814 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);
2818 /* join MESSAGE_INFORMATION */
2819 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2821 struct lcr_msg *message;
2827 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2828 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2829 message_put(message);
2830 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2831 portlist = portlist->next;
2835 /* join MESSAGE_FACILITY */
2836 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2838 struct lcr_msg *message;
2840 if (!e_ext.facility && e_ext.number[0])
2847 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2848 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2849 message_put(message);
2850 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2851 portlist = portlist->next;
2855 /* join MESSAGE_MORE */
2856 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2858 struct lcr_msg *message;
2860 new_state(EPOINT_STATE_IN_OVERLAP);
2863 if (e_join_pattern && e_ext.own_setup)
2865 /* disconnect audio */
2866 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2867 message->param.audiopath = CHANNEL_STATE_HOLD;
2868 message_put(message);
2870 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2872 if (e_dialinginfo.id[0])
2873 set_tone(portlist, "dialing");
2875 set_tone(portlist, "dialtone");
2878 if (e_ext.number[0])
2879 set_tone(portlist, "dialpbx");
2881 set_tone(portlist, "dialtone");
2884 /* join MESSAGE_PROCEEDING */
2885 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2887 struct lcr_msg *message;
2889 new_state(EPOINT_STATE_IN_PROCEEDING);
2891 /* own proceeding tone */
2894 /* connect / disconnect audio */
2895 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2896 if (e_ext.own_proceeding)
2897 message->param.audiopath = CHANNEL_STATE_HOLD;
2899 message->param.audiopath = CHANNEL_STATE_CONNECT;
2900 message_put(message);
2902 // UCPY(e_join_tone, "proceeding");
2905 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2906 message_put(message);
2907 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2909 set_tone(portlist, "proceeding");
2912 /* join MESSAGE_ALERTING */
2913 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2915 struct lcr_msg *message;
2917 new_state(EPOINT_STATE_IN_ALERTING);
2919 /* own alerting tone */
2922 /* connect / disconnect audio */
2923 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2924 if (e_ext.own_alerting)
2925 message->param.audiopath = CHANNEL_STATE_HOLD;
2927 message->param.audiopath = CHANNEL_STATE_CONNECT;
2928 message_put(message);
2932 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2933 message_put(message);
2934 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2936 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2938 set_tone(portlist, "ringing");
2941 if (e_ext.number[0])
2942 set_tone(portlist, "ringpbx");
2944 set_tone(portlist, "ringing");
2947 /* join MESSAGE_CONNECT */
2948 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2950 struct lcr_msg *message;
2952 new_state(EPOINT_STATE_CONNECT);
2953 // UCPY(e_join_tone, "");
2954 if (e_ext.number[0])
2955 e_dtmf = 1; /* allow dtmf */
2957 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2960 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2961 memcpy(&message->param, param, sizeof(union parameter));
2963 /* screen clip if prefix is required */
2964 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
2966 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2967 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2968 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2971 /* use internal caller id */
2972 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
2974 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2975 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2978 /* handle restricted caller ids */
2979 apply_callerid_restriction(&e_ext, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
2980 /* display callerid if desired for extension */
2981 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));
2983 /* use conp, if enabld */
2984 // if (!e_ext.centrex)
2985 // message->param.connectinfo.name[0] = '\0';
2988 message_put(message);
2989 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2991 set_tone(portlist, NULL);
2993 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2994 message->param.audiopath = CHANNEL_STATE_CONNECT;
2995 message_put(message);
2999 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3000 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3003 struct lcr_msg *message;
3004 struct port_list *portlist = NULL;
3007 /* be sure that we are active */
3009 e_tx_state = NOTIFY_STATE_ACTIVE;
3011 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3012 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3014 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3016 /* set time for power dialing */
3017 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3020 /* set redial tone */
3021 if (ea_endpoint->ep_portlist)
3025 set_tone(ea_endpoint->ep_portlist, "redial");
3026 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);
3027 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3028 if (e_state==EPOINT_STATE_IN_OVERLAP)
3030 new_state(EPOINT_STATE_IN_PROCEEDING);
3031 if (ea_endpoint->ep_portlist)
3033 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3034 message_put(message);
3035 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3037 /* caused the error, that the first knock sound was not there */
3038 /* set_tone(portlist, "proceeding"); */
3040 /* send display of powerdialing */
3041 if (e_ext.display_dialing)
3043 portlist = ea_endpoint->ep_portlist;
3046 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3048 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3050 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3051 message_put(message);
3052 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3053 portlist = portlist->next;
3062 if ((e_state!=EPOINT_STATE_CONNECT
3063 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3064 && e_state!=EPOINT_STATE_IN_OVERLAP
3065 && e_state!=EPOINT_STATE_IN_PROCEEDING
3066 && e_state!=EPOINT_STATE_IN_ALERTING)
3067 || !ea_endpoint->ep_portlist) /* or no port */
3069 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3070 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3071 return; /* must exit here */
3076 e_join_cause = param->disconnectinfo.cause;
3077 e_join_location = param->disconnectinfo.location;
3080 /* on release we need the audio again! */
3081 if (message_type == MESSAGE_RELEASE)
3084 ea_endpoint->ep_join_id = 0;
3086 /* disconnect and select tone */
3087 new_state(EPOINT_STATE_OUT_DISCONNECT);
3088 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3089 /* if own_cause, we must release the join */
3090 if (e_ext.own_cause /* own cause */
3091 || !e_join_pattern) /* no patterns */
3093 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);
3094 if (message_type != MESSAGE_RELEASE)
3095 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3097 } else /* else we enable audio */
3099 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3100 message->param.audiopath = CHANNEL_STATE_CONNECT;
3101 message_put(message);
3103 /* send disconnect message */
3104 SCPY(e_tone, cause);
3105 portlist = ea_endpoint->ep_portlist;
3108 set_tone(portlist, cause);
3109 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3110 portlist = portlist->next;
3114 /* join MESSAGE_SETUP */
3115 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3117 struct lcr_msg *message;
3118 // struct interface *interface;
3120 /* if we already in setup state, we just update the dialing with new digits */
3121 if (e_state == EPOINT_STATE_OUT_SETUP
3122 || e_state == EPOINT_STATE_OUT_OVERLAP)
3124 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3125 /* if digits changed, what we have already dialed */
3126 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3128 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);
3129 /* release all ports */
3130 while((portlist = ea_endpoint->ep_portlist))
3132 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3133 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3134 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3135 message_put(message);
3136 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3137 ea_endpoint->free_portlist(portlist);
3140 /* disconnect audio */
3141 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3142 message->param.audiopath = CHANNEL_STATE_HOLD;
3143 message_put(message);
3145 /* get dialing info */
3146 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3147 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3148 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3149 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3150 new_state(EPOINT_STATE_OUT_OVERLAP);
3153 e_redial = now_d + 1; /* set redial one second in the future */
3156 /* if we have a pending redial, so we just adjust the dialing number */
3159 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);
3160 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3163 if (!ea_endpoint->ep_portlist)
3165 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3167 if (ea_endpoint->ep_portlist->next)
3169 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3171 if (e_state == EPOINT_STATE_OUT_SETUP)
3174 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);
3175 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3179 /* get what we have not dialed yet */
3180 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));
3181 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3182 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3183 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3184 message_put(message);
3185 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3187 /* always store what we have dialed or queued */
3188 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3192 if (e_state != EPOINT_STATE_IDLE)
3194 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3197 /* if an internal extension is dialed, copy that number */
3198 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3199 SCPY(e_ext.number, param->setup.dialinginfo.id);
3200 /* if an internal extension is dialed, get extension's info about caller */
3201 if (e_ext.number[0])
3203 if (!read_extension(&e_ext, e_ext.number))
3205 e_ext.number[0] = '\0';
3206 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3210 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3211 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3212 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3213 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3215 /* process (voice over) data calls */
3216 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3218 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3219 memset(&e_capainfo, 0, sizeof(e_capainfo));
3220 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3221 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3222 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3225 new_state(EPOINT_STATE_OUT_SETUP);
3226 /* call special setup routine */
3230 /* join MESSAGE_mISDNSIGNAL */
3231 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3233 struct lcr_msg *message;
3237 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3238 memcpy(&message->param, param, sizeof(union parameter));
3239 message_put(message);
3240 portlist = portlist->next;
3244 /* join MESSAGE_NOTIFY */
3245 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3247 struct lcr_msg *message;
3250 if (param->notifyinfo.notify)
3252 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3253 // /* if notification was generated locally, we turn hold music on/off */
3254 // if (param->notifyinfo.local)
3255 // 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)
3260 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3262 if (!strcmp(e_tone, "hold")) // don't interrupt other tones
3266 set_tone(portlist, "");
3267 portlist = portlist->next;
3270 portlist = ea_endpoint->ep_portlist;
3275 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3279 set_tone(portlist, "hold");
3280 portlist = portlist->next;
3282 portlist = ea_endpoint->ep_portlist;
3287 /* save new state */
3288 e_tx_state = new_state;
3291 /* notify port(s) about it */
3294 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3295 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3296 /* handle restricted caller ids */
3297 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3298 /* display callerid if desired for extension */
3299 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));
3300 message_put(message);
3301 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3302 portlist = portlist->next;
3306 /* JOIN sends messages to the endpoint
3308 void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, union parameter *param)
3310 struct port_list *portlist;
3311 struct lcr_msg *message;
3315 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3319 portlist = ea_endpoint->ep_portlist;
3321 /* send MESSAGE_DATA to port */
3322 if (message_type == MESSAGE_DATA)
3324 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3326 /* skip if no port relation */
3329 /* skip if more than one port relation */
3332 /* forward audio data to port */
3333 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3338 // PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active JOIN (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
3339 switch(message_type)
3341 /* JOIN SENDS TONE message */
3343 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received tone message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->tone.name);
3344 set_tone(portlist, param->tone.name);
3347 /* JOIN SENDS CRYPT message */
3349 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);
3350 join_crypt(portlist, message_type, param);
3353 /* JOIN sends INFORMATION message */
3354 case MESSAGE_INFORMATION:
3355 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);
3356 join_information(portlist, message_type, param);
3359 /* JOIN sends FACILITY message */
3360 case MESSAGE_FACILITY:
3361 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);
3362 join_facility(portlist, message_type, param);
3365 /* JOIN sends OVERLAP message */
3366 case MESSAGE_OVERLAP:
3367 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);
3368 if (e_state!=EPOINT_STATE_IN_SETUP
3369 && e_state!=EPOINT_STATE_IN_OVERLAP)
3371 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3374 join_overlap(portlist, message_type, param);
3377 /* JOIN sends PROCEEDING message */
3378 case MESSAGE_PROCEEDING:
3379 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);
3380 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3382 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3385 join_proceeding(portlist, message_type, param);
3388 /* JOIN sends ALERTING message */
3389 case MESSAGE_ALERTING:
3390 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);
3391 if (e_state!=EPOINT_STATE_IN_OVERLAP
3392 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3394 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3397 join_alerting(portlist, message_type, param);
3400 /* JOIN sends CONNECT message */
3401 case MESSAGE_CONNECT:
3402 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);
3403 if (e_state!=EPOINT_STATE_IN_OVERLAP
3404 && e_state!=EPOINT_STATE_IN_PROCEEDING
3405 && e_state!=EPOINT_STATE_IN_ALERTING)
3407 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3410 join_connect(portlist, message_type, param);
3413 /* JOIN sends DISCONNECT/RELEASE message */
3414 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3415 case MESSAGE_RELEASE: /* JOIN releases */
3416 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);
3417 join_disconnect_release(message_type, param);
3420 /* JOIN sends SETUP message */
3422 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);
3423 join_setup(portlist, message_type, param);
3426 /* JOIN sends special mISDNSIGNAL message */
3427 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3428 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);
3429 join_mISDNsignal(portlist, message_type, param);
3432 #warning was ist hiermit
3434 /* JOIN requests bchannel */
3435 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3436 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel assignment %d from join.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
3437 /* only one port is expected to be connected to bchannel */
3444 set_tone(portlist, NULL);
3445 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3446 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3450 /* JOIN has pattern available */
3451 case MESSAGE_PATTERN: /* indicating pattern available */
3452 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);
3453 if (!e_join_pattern)
3455 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3460 set_tone(portlist, NULL);
3461 portlist = portlist->next;
3463 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3464 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3465 message->param.audiopath = CHANNEL_STATE_CONNECT;
3466 message_put(message);
3467 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3468 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_REMOTE_AUDIO);
3469 // message->param.audiopath = CHANNEL_STATE_CONNECT;
3470 // message_put(message);
3471 // patterns are available, remote already connected audio
3475 /* JOIN has no pattern available */
3476 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3477 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);
3480 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3482 /* disconnect our audio tx and rx */
3483 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3484 message->param.audiopath = CHANNEL_STATE_HOLD;
3485 message_put(message);
3490 /* JOIN (dunno at the moment) */
3491 case MESSAGE_REMOTE_AUDIO:
3492 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);
3493 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3494 message->param.audiopath = param->channel;
3495 message_put(message);
3499 /* JOIN sends a notify message */
3500 case MESSAGE_NOTIFY:
3501 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);
3502 join_notify(portlist, message_type, param);
3506 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);
3511 /* pick_join will connect the first incoming call found. the endpoint
3512 * will receivce a MESSAGE_CONNECT.
3514 int match_list(char *list, char *item)
3516 char *end, *next = NULL;
3518 /* no list make matching */
3524 /* eliminate white spaces */
3525 while (*list <= ' ')
3532 /* if end of list is reached, we return */
3533 if (list[0] == '\0')
3535 /* if we have more than one entry (left) */
3536 if ((end = strchr(list, ',')))
3539 next = end = strchr(list, '\0');
3540 while (*(end-1) <= ' ')
3542 /* if string part matches item */
3543 if (!strncmp(list, item, end-list))
3549 void EndpointAppPBX::pick_join(char *extensions)
3551 struct lcr_msg *message;
3552 struct port_list *portlist;
3554 class EndpointAppPBX *eapp, *found;
3556 class JoinPBX *joinpbx;
3557 struct join_relation *relation;
3560 /* find an endpoint that is ringing internally or vbox with higher priority */
3563 eapp = apppbx_first;
3566 if (eapp!=this && ea_endpoint->ep_portlist)
3568 portlist = eapp->ea_endpoint->ep_portlist;
3571 if ((port = find_port_id(portlist->port_id)))
3573 if (port->p_type == PORT_TYPE_VBOX_OUT)
3575 if (match_list(extensions, eapp->e_ext.number))
3582 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3583 && port->p_state==PORT_STATE_OUT_ALERTING)
3584 if (match_list(extensions, eapp->e_ext.number))
3589 portlist = portlist->next;
3597 /* if no endpoint found */
3600 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);
3602 set_tone(ea_endpoint->ep_portlist, "cause_10");
3603 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3604 new_state(EPOINT_STATE_OUT_DISCONNECT);
3609 if (ea_endpoint->ep_join_id)
3611 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3614 if (!eapp->ea_endpoint->ep_join_id)
3616 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3619 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3622 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3625 if (join->j_type != JOIN_TYPE_PBX)
3627 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3630 joinpbx = (class JoinPBX *)join;
3631 relation = joinpbx->j_relation;
3634 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3637 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3639 relation = relation->next;
3642 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3647 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3649 if (options.deb & DEBUG_EPOINT)
3651 class Join *debug_c = join_first;
3652 class Endpoint *debug_e = epoint_first;
3653 class Port *debug_p = port_first;
3655 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3657 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3660 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3661 debug_c = debug_c->next;
3663 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3666 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3667 debug_e = debug_e->next;
3669 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3672 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3673 debug_p = debug_p->next;
3678 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3679 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3680 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3682 /* connnecting our endpoint */
3683 new_state(EPOINT_STATE_CONNECT);
3685 set_tone(ea_endpoint->ep_portlist, NULL);
3687 /* now we send a release to the ringing endpoint */
3688 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3689 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3690 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3691 message_put(message);
3693 /* we send a connect to the join with our caller id */
3694 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3695 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3696 message->param.connectinfo.present = e_callerinfo.present;
3697 message->param.connectinfo.screen = e_callerinfo.screen;
3698 message->param.connectinfo.itype = e_callerinfo.itype;
3699 message->param.connectinfo.ntype = e_callerinfo.ntype;
3700 message_put(message);
3702 /* we send a connect to our port with the remote callerid */
3703 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3704 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3705 message->param.connectinfo.present = eapp->e_callerinfo.present;
3706 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3707 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3708 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3709 /* handle restricted caller ids */
3710 apply_callerid_restriction(&e_ext, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
3711 /* display callerid if desired for extension */
3712 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));
3713 message_put(message);
3715 /* we send a connect to the audio path (not for vbox) */
3716 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3717 message->param.audiopath = CHANNEL_STATE_CONNECT;
3718 message_put(message);
3720 /* beeing paranoid, we make call update */
3721 joinpbx->j_updatebridge = 1;
3723 if (options.deb & DEBUG_EPOINT)
3725 class Join *debug_c = join_first;
3726 class Endpoint *debug_e = epoint_first;
3727 class Port *debug_p = port_first;
3729 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3731 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3734 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3735 debug_c = debug_c->next;
3737 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3740 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3741 debug_e = debug_e->next;
3743 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3746 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3747 debug_p = debug_p->next;
3753 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3755 void EndpointAppPBX::join_join(void)
3757 struct lcr_msg *message;
3758 struct join_relation *our_relation, *other_relation;
3759 struct join_relation **our_relation_pointer, **other_relation_pointer;
3760 class Join *our_join, *other_join;
3761 class JoinPBX *our_joinpbx, *other_joinpbx;
3762 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3763 class Port *our_port, *other_port;
3764 class Pdss1 *our_pdss1, *other_pdss1;
3766 /* are we a candidate to join a join */
3767 our_join = find_join_id(ea_endpoint->ep_join_id);
3770 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3773 if (our_join->j_type != JOIN_TYPE_PBX)
3775 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3778 our_joinpbx = (class JoinPBX *)our_join;
3779 if (!ea_endpoint->ep_portlist)
3781 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3784 if (!e_ext.number[0])
3786 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3789 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3792 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3795 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3797 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3800 our_pdss1 = (class Pdss1 *)our_port;
3802 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3803 other_eapp = apppbx_first;
3806 if (other_eapp == this)
3808 other_eapp = other_eapp->next;
3811 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);
3812 if (other_eapp->e_ext.number[0] /* has terminal */
3813 && other_eapp->ea_endpoint->ep_portlist /* has port */
3814 && other_eapp->ea_endpoint->ep_join_id) /* has join */
3816 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3817 if (other_port) /* port still exists */
3819 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3820 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3822 other_pdss1 = (class Pdss1 *)other_port;
3823 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);
3824 if (other_pdss1->p_m_hold /* port is on hold */
3825 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3826 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3830 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3834 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3837 other_eapp = other_eapp->next;
3841 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3844 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3846 /* if we have the same join */
3847 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
3849 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
3852 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3855 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3858 if (other_join->j_type != JOIN_TYPE_PBX)
3860 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3863 other_joinpbx = (class JoinPBX *)other_join;
3864 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
3866 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3870 /* remove relation to endpoint for join on hold */
3871 other_relation = other_joinpbx->j_relation;
3872 other_relation_pointer = &other_joinpbx->j_relation;
3873 while(other_relation)
3875 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
3877 /* detach other endpoint on hold */
3878 *other_relation_pointer = other_relation->next;
3879 FREE(other_relation, sizeof(struct join_relation));
3881 other_relation = *other_relation_pointer;
3882 other_eapp->ea_endpoint->ep_join_id = 0;
3886 /* change join/hold pointer of endpoint to the new join */
3887 temp_epoint = find_epoint_id(other_relation->epoint_id);
3890 if (temp_epoint->ep_join_id == other_join->j_serial)
3891 temp_epoint->ep_join_id = our_join->j_serial;
3894 other_relation_pointer = &other_relation->next;
3895 other_relation = other_relation->next;
3897 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3899 /* join call relations */
3900 our_relation = our_joinpbx->j_relation;
3901 our_relation_pointer = &our_joinpbx->j_relation;
3904 our_relation_pointer = &our_relation->next;
3905 our_relation = our_relation->next;
3907 *our_relation_pointer = other_joinpbx->j_relation;
3908 other_joinpbx->j_relation = NULL;
3909 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3911 /* release endpoint on hold */
3912 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3913 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3914 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3915 message_put(message);
3917 /* if we are not a partyline, we get partyline state from other join */
3918 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3920 /* remove empty join */
3922 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3924 /* mixer must update */
3925 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
3927 /* we send a retrieve to that endpoint */
3928 // mixer will update the hold-state of the join and send it to the endpoints is changes
3932 /* check if we have an external call
3933 * this is used to check for encryption ability
3935 int EndpointAppPBX::check_external(char **errstr, class Port **port)
3937 struct join_relation *relation;
3939 class JoinPBX *joinpbx;
3940 class Endpoint *epoint;
3942 /* some paranoia check */
3943 if (!ea_endpoint->ep_portlist)
3945 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3946 *errstr = "No Call";
3949 if (!e_ext.number[0])
3951 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
3952 *errstr = "No Call";
3956 /* check if we have a join with 2 parties */
3957 join = find_join_id(ea_endpoint->ep_join_id);
3960 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
3961 *errstr = "No Call";
3964 if (join->j_type != JOIN_TYPE_PBX)
3966 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
3967 *errstr = "No PBX Call";
3970 joinpbx = (class JoinPBX *)join;
3971 relation = joinpbx->j_relation;
3974 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
3975 *errstr = "No Call";
3978 if (!relation->next)
3980 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
3981 *errstr = "No Call";
3984 if (relation->next->next)
3986 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
3987 *errstr = "Err: Conference";
3990 if (relation->epoint_id == ea_endpoint->ep_serial)
3992 relation = relation->next;
3993 if (relation->epoint_id == ea_endpoint->ep_serial)
3995 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
3996 *errstr = "Software Error";
4001 /* check remote port for external call */
4002 epoint = find_epoint_id(relation->epoint_id);
4005 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4006 *errstr = "No Call";
4009 if (!epoint->ep_portlist)
4011 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4012 *errstr = "No Call";
4015 *port = find_port_id(epoint->ep_portlist->port_id);
4018 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4019 *errstr = "No Call";
4022 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4024 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4025 *errstr = "No Ext Call";
4028 if ((*port)->p_state != PORT_STATE_CONNECT)
4030 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4031 *errstr = "No Ext Connect";
4037 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned long port_id, int dir)
4039 char *logtext = "unknown";
4042 switch(message_type)
4045 trace_header("SETUP", dir);
4046 if (dir == DIRECTION_OUT)
4047 add_trace("to", NULL, "CH(%lu)", port_id);
4048 if (dir == DIRECTION_IN)
4049 add_trace("from", NULL, "CH(%lu)", port_id);
4050 if (param->setup.callerinfo.extension[0])
4051 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4052 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
4053 switch(param->setup.callerinfo.present)
4055 case INFO_PRESENT_RESTRICTED:
4056 add_trace("caller id", "present", "restricted");
4058 case INFO_PRESENT_ALLOWED:
4059 add_trace("caller id", "present", "allowed");
4062 add_trace("caller id", "present", "not available");
4064 if (param->setup.redirinfo.id[0])
4066 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
4067 switch(param->setup.redirinfo.present)
4069 case INFO_PRESENT_RESTRICTED:
4070 add_trace("redir'ing", "present", "restricted");
4072 case INFO_PRESENT_ALLOWED:
4073 add_trace("redir'ing", "present", "allowed");
4076 add_trace("redir'ing", "present", "not available");
4079 if (param->setup.dialinginfo.id[0])
4080 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4084 case MESSAGE_OVERLAP:
4085 trace_header("SETUP ACKNOWLEDGE", dir);
4086 if (dir == DIRECTION_OUT)
4087 add_trace("to", NULL, "CH(%lu)", port_id);
4088 if (dir == DIRECTION_IN)
4089 add_trace("from", NULL, "CH(%lu)", port_id);
4093 case MESSAGE_PROCEEDING:
4094 trace_header("PROCEEDING", dir);
4095 if (dir == DIRECTION_OUT)
4096 add_trace("to", NULL, "CH(%lu)", port_id);
4097 if (dir == DIRECTION_IN)
4098 add_trace("from", NULL, "CH(%lu)", port_id);
4102 case MESSAGE_ALERTING:
4103 trace_header("ALERTING", dir);
4104 if (dir == DIRECTION_OUT)
4105 add_trace("to", NULL, "CH(%lu)", port_id);
4106 if (dir == DIRECTION_IN)
4107 add_trace("from", NULL, "CH(%lu)", port_id);
4111 case MESSAGE_CONNECT:
4112 trace_header("CONNECT", dir);
4113 if (dir == DIRECTION_OUT)
4114 add_trace("to", NULL, "CH(%lu)", port_id);
4115 if (dir == DIRECTION_IN)
4116 add_trace("from", NULL, "CH(%lu)", port_id);
4117 if (param->connectinfo.extension[0])
4118 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4119 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
4120 switch(param->connectinfo.present)
4122 case INFO_PRESENT_RESTRICTED:
4123 add_trace("connect id", "present", "restricted");
4125 case INFO_PRESENT_ALLOWED:
4126 add_trace("connect id", "present", "allowed");
4129 add_trace("connect id", "present", "not available");
4134 case MESSAGE_DISCONNECT:
4135 case MESSAGE_RELEASE:
4136 if (message_type == MESSAGE_DISCONNECT)
4137 trace_header("DISCONNECT", dir);
4139 trace_header("RELEASE", dir);
4140 if (dir == DIRECTION_OUT)
4141 add_trace("to", NULL, "CH(%lu)", port_id);
4142 if (dir == DIRECTION_IN)
4143 add_trace("from", NULL, "CH(%lu)", port_id);
4144 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4145 switch(param->disconnectinfo.location)
4148 add_trace("cause", "location", "0-User");
4150 case LOCATION_PRIVATE_LOCAL:
4151 add_trace("cause", "location", "1-Local-PBX");
4153 case LOCATION_PUBLIC_LOCAL:
4154 add_trace("cause", "location", "2-Local-Exchange");
4156 case LOCATION_TRANSIT:
4157 add_trace("cause", "location", "3-Transit");
4159 case LOCATION_PUBLIC_REMOTE:
4160 add_trace("cause", "location", "4-Remote-Exchange");
4162 case LOCATION_PRIVATE_REMOTE:
4163 add_trace("cause", "location", "5-Remote-PBX");
4165 case LOCATION_INTERNATIONAL:
4166 add_trace("cause", "location", "7-International-Exchange");
4168 case LOCATION_BEYOND:
4169 add_trace("cause", "location", "10-Beyond-Interworking");
4172 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4177 case MESSAGE_NOTIFY:
4178 switch(param->notifyinfo.notify)
4184 logtext = "USER_SUSPENDED";
4187 logtext = "BEARER_SERVICE_CHANGED";
4190 logtext = "USER_RESUMED";
4193 logtext = "CONFERENCE_ESTABLISHED";
4196 logtext = "CONFERENCE_DISCONNECTED";
4199 logtext = "OTHER_PARTY_ADDED";
4202 logtext = "ISOLATED";
4205 logtext = "REATTACHED";
4208 logtext = "OTHER_PARTY_ISOLATED";
4211 logtext = "OTHER_PARTY_REATTACHED";
4214 logtext = "OTHER_PARTY_SPLIT";
4217 logtext = "OTHER_PARTY_DISCONNECTED";
4220 logtext = "CONFERENCE_FLOATING";
4223 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4226 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4229 logtext = "CALL_IS_A_WAITING_CALL";
4232 logtext = "DIVERSION_ACTIVATED";
4235 logtext = "RESERVED_CT_1";
4238 logtext = "RESERVED_CT_2";
4241 logtext = "REVERSE_CHARGING";
4244 logtext = "REMOTE_HOLD";
4247 logtext = "REMOTE_RETRIEVAL";
4250 logtext = "CALL_IS_DIVERTING";
4253 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4257 trace_header("NOTIFY", dir);
4258 if (dir == DIRECTION_OUT)
4259 add_trace("to", NULL, "CH(%lu)", port_id);
4260 if (dir == DIRECTION_IN)
4261 add_trace("from", NULL, "CH(%lu)", port_id);
4262 if (param->notifyinfo.notify)
4263 add_trace("indicator", NULL, "%s", logtext);
4264 if (param->notifyinfo.id[0])
4266 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
4267 switch(param->notifyinfo.present)
4269 case INFO_PRESENT_RESTRICTED:
4270 add_trace("redir'on", "present", "restricted");
4272 case INFO_PRESENT_ALLOWED:
4273 add_trace("redir'on", "present", "allowed");
4276 add_trace("redir'on", "present", "not available");
4279 if (param->notifyinfo.display[0])
4280 add_trace("display", NULL, "%s", param->notifyinfo.display);
4284 case MESSAGE_INFORMATION:
4285 trace_header("INFORMATION", dir);
4286 if (dir == DIRECTION_OUT)
4287 add_trace("to", NULL, "CH(%lu)", port_id);
4288 if (dir == DIRECTION_IN)
4289 add_trace("from", NULL, "CH(%lu)", port_id);
4290 add_trace("dialing", NULL, "%s", param->information.id);
4294 case MESSAGE_FACILITY:
4295 trace_header("FACILITY", dir);
4296 if (dir == DIRECTION_OUT)
4297 add_trace("to", NULL, "CH(%lu)", port_id);
4298 if (dir == DIRECTION_IN)
4299 add_trace("from", NULL, "CH(%lu)", port_id);
4304 trace_header("TONE", dir);
4305 if (dir == DIRECTION_OUT)
4306 add_trace("to", NULL, "CH(%lu)", port_id);
4307 if (dir == DIRECTION_IN)
4308 add_trace("from", NULL, "CH(%lu)", port_id);
4309 if (param->tone.name[0])
4311 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4312 add_trace("name", NULL, "%s", param->tone.name);
4314 add_trace("off", NULL, NULL);
4318 case MESSAGE_SUSPEND:
4319 case MESSAGE_RESUME:
4320 if (message_type == MESSAGE_SUSPEND)
4321 trace_header("SUSPEND", dir);
4323 trace_header("RESUME", dir);
4324 if (dir == DIRECTION_OUT)
4325 add_trace("to", NULL, "CH(%lu)", port_id);
4326 if (dir == DIRECTION_IN)
4327 add_trace("from", NULL, "CH(%lu)", port_id);
4328 if (param->parkinfo.len)
4329 add_trace("length", NULL, "%d", param->parkinfo.len);
4334 case MESSAGE_BCHANNEL:
4335 trace_header("BCHANNEL", dir);
4336 switch(param->bchannel.type)
4338 case BCHANNEL_REQUEST:
4339 add_trace("type", NULL, "request");
4341 case BCHANNEL_ASSIGN:
4342 add_trace("type", NULL, "assign");
4344 case BCHANNEL_ASSIGN_ACK:
4345 add_trace("type", NULL, "assign_ack");
4347 case BCHANNEL_REMOVE:
4348 add_trace("type", NULL, "remove");
4350 case BCHANNEL_REMOVE_ACK:
4351 add_trace("type", NULL, "remove_ack");
4354 if (param->bchannel.addr)
4355 add_trace("address", NULL, "%x", param->bchannel.addr);
4361 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4365 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4367 struct lcr_msg *message;
4371 if (!portlist->port_id)
4374 if (!e_connectedmode)
4376 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4377 message->param.disconnectinfo.cause = cause;
4378 message->param.disconnectinfo.location = location;
4380 SCPY(message->param.disconnectinfo.display, display);
4382 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4385 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4387 SCPY(message->param.notifyinfo.display, display);
4389 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4391 message_put(message);
4392 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);