1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 #include <sys/types.h>
23 class EndpointAppPBX *apppbx_first = NULL;
26 * EndpointAppPBX constructor
28 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
30 class EndpointAppPBX **apppointer;
32 /* add application to chain */
34 apppointer = &apppbx_first;
36 apppointer = &((*apppointer)->next);
40 memset(&e_ext, 0, sizeof(struct extension));
41 // *************** NOTE: also change value in read_extension() **************
42 e_ext.rights = 4; /* international */
43 e_ext.tout_setup = 120;
44 e_ext.tout_dialing = 120;
45 e_ext.tout_proceeding = 120;
46 e_ext.tout_alerting = 120;
47 e_ext.tout_disconnect = 120;
48 // e_ext.tout_hold = 900;
49 // e_ext.tout_park = 900;
50 e_ext.rxvol = e_ext.txvol = 0;
51 e_state = EPOINT_STATE_IDLE;
52 e_ext.number[0] = '\0';
53 e_extension_interface[0] = '\0';
54 memset(&e_callerinfo, 0, sizeof(struct caller_info));
55 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
56 memset(&e_connectinfo, 0, sizeof(struct connect_info));
57 memset(&e_redirinfo, 0, sizeof(struct redir_info));
58 memset(&e_capainfo, 0, sizeof(struct capa_info));
61 e_ruleset = ruleset_main;
63 e_rule = e_ruleset->rule_first;
68 e_match_to_action = NULL;
70 e_extdialing = e_dialinginfo.id;
74 // e_join_tone[0] = e_hold_tone[0] = '\0';
75 e_join_pattern /*= e_hold_pattern*/ = 0;
78 e_adminid = 0; // will be set, if call was initiated via admin socket
83 e_cbdialing[0] = '\0';
86 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
93 e_password_timeout = 0;
94 e_multipoint_cause = 0;
95 e_multipoint_location = 0;
96 e_dialing_queue[0] = '\0';
98 e_crypt_state = CM_ST_NULL;
99 e_crypt_keyengine_busy = 0;
100 e_crypt_info[0] = '\0';
103 e_tx_state = NOTIFY_STATE_ACTIVE;
104 e_rx_state = NOTIFY_STATE_ACTIVE;
105 e_join_cause = e_join_location = 0;
106 /*********************************
107 *********************************
108 ********* ATTENTION *************
109 *********************************
110 *********************************/
111 /* if you add new values, that must be initialized, also check if they must
112 * be initialized when doing callback
118 * EpointAppPBX destructor
120 EndpointAppPBX::~EndpointAppPBX(void)
122 class EndpointAppPBX *temp, **tempp;
126 tempp = &apppbx_first;
136 FATAL("Endpoint not in endpoint's list.\n");
143 * trace header for application
145 void EndpointAppPBX::trace_header(char *name, int direction)
149 char msgtext[sizeof(_trace.name)];
153 /* init trace with given values */
156 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype),
160 ea_endpoint->ep_serial,
167 /* set new endpoint state
169 void EndpointAppPBX::new_state(int state)
172 if (e_state != state)
174 trace_header("NEW STATE", DIRECTION_NONE);
175 add_trace("state", "old", "%s", state_name[e_state]);
176 add_trace("state", "new", "%s", state_name[state]);
184 /* release join and port (as specified)
186 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
188 struct port_list *portlist;
189 struct message *message;
192 /* message to test call */
193 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
195 /* if a release is pending */
196 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
198 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
199 if (ea_endpoint->ep_join_id)
201 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
202 message->param.disconnectinfo.cause = joincause;
203 message->param.disconnectinfo.location = joinlocation;
204 message_put(message);
205 ea_endpoint->ep_join_id = 0;
209 if (release != RELEASE_PORT_JOINONLY)
212 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
217 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
219 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
220 while((portlist = ea_endpoint->ep_portlist))
222 if (portlist->port_id)
224 SPRINT(cause, "cause_%02x", portcause);
225 set_tone(portlist, cause);
226 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
227 message->param.disconnectinfo.cause = portcause;
228 message->param.disconnectinfo.location = portlocation;
229 message_put(message);
230 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
232 ea_endpoint->free_portlist(portlist);
235 /* if callback is enabled, call back with the given caller id */
238 /* reset some stuff */
239 new_state(EPOINT_STATE_IDLE);
240 memset(&e_connectinfo, 0, sizeof(struct connect_info));
241 memset(&e_redirinfo, 0, sizeof(struct redir_info));
242 e_start = e_stop = 0;
243 e_ruleset = ruleset_main;
245 e_rule = e_ruleset->rule_first;
247 e_action_timeout = 0;
249 e_match_to_action = NULL;
251 e_extdialing = e_dialinginfo.id;
258 e_multipoint_cause = 0;
259 e_multipoint_location = 0;
260 e_dialing_queue[0] = '\0';
262 e_crypt_state = CM_ST_NULL;
263 e_crypt_keyengine_busy = 0;
264 e_crypt_info[0] = '\0';
268 e_tx_state = NOTIFY_STATE_ACTIVE;
269 e_rx_state = NOTIFY_STATE_ACTIVE;
270 e_join_cause = e_join_location = 0;
272 /* the caller info of the callback user */
273 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
274 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
275 /* create dialing by callerinfo */
276 if (e_ext.number[0] && e_extension_interface[0])
278 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
279 /* create callback to the current terminal */
280 SCPY(e_dialinginfo.id, e_ext.number);
281 SCPY(e_dialinginfo.interfaces, e_extension_interface);
282 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
283 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
288 SCPY(e_dialinginfo.id, e_cbto);
291 /* numberrize caller id and use it to dial to the callback */
292 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
294 e_dialinginfo.itype = INFO_ITYPE_ISDN;
295 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
296 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
301 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
302 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
308 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
309 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
311 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");
313 /* caller id is not restricted, so we do nothing */
314 if (*present != INFO_PRESENT_RESTRICTED)
317 /* only extensions are restricted */
321 /* if we enabled anonymouse ignore */
322 if (ext->anon_ignore)
325 /* else we remove the caller id */
329 *ntype = INFO_NTYPE_UNKNOWN;
331 // *screen = INFO_SCREEN_USER;
332 // maybe we should not make voip address anonymous
335 // maybe it's no fraud to present extension id
337 // extension[0] = '\0';
342 /* used display message to display callerid as available */
343 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *extension, char *name)
345 static char display[81];
348 char *cid = numberrize_callerinfo(id, ntype);
350 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");
359 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
361 /* internal extension's caller id */
362 if (extension[0] && e_ext.display_int)
365 SCAT(display, extension);
368 if (itype == INFO_ITYPE_VBOX)
369 SCAT(display, "(vbox)");
371 SCAT(display, "(int)");
374 /* external caller id */
375 if (!extension[0] && e_ext.display_ext)
381 if (present == INFO_PRESENT_RESTRICTED)
382 SCAT(display, "anonymous");
384 SCAT(display, "unknown");
391 /* display if callerid is anonymouse but available due anon-ignore */
392 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
395 SCAT(display, "unknown");
398 SCAT(display, " anon");
401 /* display if callerid is anonymouse but available due anon-ignore */
402 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
408 if (present == INFO_PRESENT_RESTRICTED)
409 SCAT(display, "anonymous");
411 SCAT(display, "unknown");
416 SCAT(display, " fake");
420 if (name[0] && e_ext.display_name)
422 if (!display[0] && cid[0])
433 * uses the current state to notify activity
435 void EndpointAppPBX::notify_active(void)
437 struct port_list *portlist = ea_endpoint->ep_portlist;
438 struct message *message;
443 case NOTIFY_STATE_ACTIVE:
444 /* we are already active, so we don't do anything */
447 case NOTIFY_STATE_SUSPEND:
448 notify = INFO_NOTIFY_USER_RESUMED;
451 set_tone(portlist, NULL);
452 portlist = portlist->next;
454 portlist = ea_endpoint->ep_portlist;
457 case NOTIFY_STATE_HOLD:
458 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
461 set_tone(portlist, NULL);
462 portlist = portlist->next;
464 portlist = ea_endpoint->ep_portlist;
467 case NOTIFY_STATE_CONFERENCE:
468 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
471 set_tone(portlist, NULL);
472 portlist = portlist->next;
474 portlist = ea_endpoint->ep_portlist;
478 PERROR("unknown e_tx_state = %d\n", e_tx_state);
484 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
485 message->param.notifyinfo.notify = notify;
486 message_put(message);
487 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
488 portlist = portlist->next;
494 * keypad functions during call. one example to use this is to put a call on hold or start a conference
496 void EndpointAppPBX::keypad_function(char digit)
499 /* we must be in a call, in order to send messages to the call */
500 if (e_ext.number[0] == '\0')
502 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
508 /* join conference */
510 if (ea_endpoint->ep_join_id == 0)
512 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
515 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
521 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
525 /* crypt key-exchange */
527 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
533 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
538 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
543 /* set tone pattern for port */
544 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
546 struct message *message;
551 /* store for suspended processes */
555 if (e_join_pattern /* pattern are provided */
556 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
557 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
558 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
559 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
560 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
561 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
562 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
563 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
564 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
565 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
566 && tone[0] && !!strncmp(tone,"crypt_*",6))
568 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
574 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
575 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
576 SCPY(message->param.tone.name, tone);
577 message_put(message);
578 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
581 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
588 * hunts an mISDNport that is available for an outgoing call
589 * if no ifname was given, any interface that is not an extension
592 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
594 struct interface *interface;
595 struct interface_port *ifport, *ifport_start;
596 struct select_channel *selchannel;
597 struct mISDNport *mISDNport;
600 interface = interface_first;
602 /* first find the given interface or, if not given, one with no extension */
607 /* check for given interface */
610 if (!strcasecmp(interface->name, ifname))
612 /* found explicit interface */
613 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
614 add_trace("interface", NULL, "%s", ifname);
621 if (!interface->extension)
623 /* found non extension */
624 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
625 add_trace("interface", NULL, "%s", interface->name);
631 interface = interface->next;
635 /* see if interface has ports */
636 if (!interface->ifport)
639 trace_header("CHANNEL SELECTION (interface has no active ports, skipping)", DIRECTION_NONE);
640 add_trace("interface", NULL, "%s", interface->name);
642 interface = interface->next;
646 /* select port by algorithm */
647 ifport_start = interface->ifport;
649 if (interface->hunt == HUNT_ROUNDROBIN)
651 while(ifport_start->next && index<interface->hunt_next)
653 ifport_start = ifport_start->next;
656 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
657 add_trace("port", NULL, "%d", ifport_start->portnum);
658 add_trace("position", NULL, "%d", index);
663 ifport = ifport_start;
666 /* see if port is available */
667 if (!ifport->mISDNport)
669 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
670 add_trace("port", NULL, "%d", ifport->portnum);
671 add_trace("position", NULL, "%d", index);
675 mISDNport = ifport->mISDNport;
677 /* see if port is administratively blocked */
680 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
681 add_trace("port", NULL, "%d", ifport->portnum);
682 add_trace("position", NULL, "%d", index);
687 /* see if link is up on PTP*/
688 if (mISDNport->ptp && !mISDNport->l2link)
690 trace_header("CHANNEL SELECTION (port is ptp with layer 2 down, skipping)", DIRECTION_NONE);
691 add_trace("port", NULL, "%d", ifport->portnum);
692 add_trace("position", NULL, "%d", index);
697 /* check for channel form selection list */
699 selchannel = ifport->out_channel;
702 switch(selchannel->channel)
704 case CHANNEL_FREE: /* free channel */
705 if (mISDNport->b_reserved >= mISDNport->b_num)
706 break; /* all channel in use or reserverd */
709 while(i < mISDNport->b_num)
711 if (mISDNport->b_port[i] == NULL)
713 *channel = i+1+(i>=15);
714 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
715 add_trace("port", NULL, "%d", ifport->portnum);
716 add_trace("position", NULL, "%d", index);
717 add_trace("channel", NULL, "%d", *channel);
725 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
726 add_trace("port", NULL, "%d", ifport->portnum);
727 add_trace("position", NULL, "%d", index);
731 case CHANNEL_ANY: /* don't ask for channel */
732 if (mISDNport->b_reserved >= mISDNport->b_num)
734 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
735 add_trace("port", NULL, "%d", ifport->portnum);
736 add_trace("position", NULL, "%d", index);
737 add_trace("total", NULL, "%d", mISDNport->b_num);
738 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
740 break; /* all channel in use or reserverd */
742 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
743 add_trace("port", NULL, "%d", ifport->portnum);
744 add_trace("position", NULL, "%d", index);
746 *channel = CHANNEL_ANY;
749 case CHANNEL_NO: /* call waiting */
750 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
751 add_trace("port", NULL, "%d", ifport->portnum);
752 add_trace("position", NULL, "%d", index);
754 *channel = CHANNEL_NO;
758 if (selchannel->channel<1 || selchannel->channel==16)
760 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
761 add_trace("port", NULL, "%d", ifport->portnum);
762 add_trace("position", NULL, "%d", index);
763 add_trace("channel", NULL, "%d", selchannel->channel);
765 break; /* invalid channels */
767 i = selchannel->channel-1-(selchannel->channel>=17);
768 if (i >= mISDNport->b_num)
770 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
771 add_trace("port", NULL, "%d", ifport->portnum);
772 add_trace("position", NULL, "%d", index);
773 add_trace("channel", NULL, "%d", selchannel->channel);
774 add_trace("channels", NULL, "%d", mISDNport->b_num);
776 break; /* channel not in port */
778 if (mISDNport->b_port[i] == NULL)
780 *channel = selchannel->channel;
781 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
782 add_trace("port", NULL, "%d", ifport->portnum);
783 add_trace("position", NULL, "%d", index);
784 add_trace("channel", NULL, "%d", *channel);
791 break; /* found channel */
792 selchannel = selchannel->next;
795 /* if channel was found, return mISDNport and channel */
798 /* setting next port to start next time */
799 if (interface->hunt == HUNT_ROUNDROBIN)
804 interface->hunt_next = index;
810 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
811 add_trace("port", NULL, "%d", ifport->portnum);
812 add_trace("position", NULL, "%d", index);
816 /* go next port, until all ports are checked */
818 ifport = ifport->next;
822 ifport = interface->ifport;
824 if (ifport != ifport_start)
827 return(NULL); /* no port found */
830 /* outgoing setup to port(s)
831 * ports will be created and a setup is sent if everything is ok. otherwhise
832 * the endpoint is destroyed.
834 void EndpointAppPBX::out_setup(void)
836 struct dialing_info dialinginfo;
838 // class pdss1 *pdss1;
839 struct port_list *portlist;
840 struct message *message;
842 int cause = CAUSE_RESSOURCEUNAVAIL;
845 struct mISDNport *mISDNport;
848 class EndpointAppPBX *atemp;
849 // char allowed_ports[256];
851 char ifname[sizeof(e_ext.interfaces)],
853 struct port_settings port_settings;
857 /* create settings for creating port */
858 memset(&port_settings, 0, sizeof(port_settings));
860 SCPY(port_settings.tones_dir, e_ext.tones_dir);
862 SCPY(port_settings.tones_dir, options.tones_dir);
863 port_settings.tout_setup = e_ext.tout_setup;
864 port_settings.tout_dialing = e_ext.tout_dialing;
865 port_settings.tout_proceeding = e_ext.tout_proceeding;
866 port_settings.tout_alerting = e_ext.tout_alerting;
867 port_settings.tout_disconnect = e_ext.tout_disconnect;
868 // port_settings.tout_hold = e_ext.tout_hold;
869 // port_settings.tout_park = e_ext.tout_park;
870 port_settings.no_seconds = e_ext.no_seconds;
872 /* 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 */
874 /* check what dialinginfo.itype we got */
875 switch(e_dialinginfo.itype)
877 /* *********************** call to extension or vbox */
878 case INFO_ITYPE_ISDN_EXTENSION:
879 /* check if we deny incoming calls when we use an extension */
880 if (e_ext.noknocking)
882 atemp = apppbx_first;
886 if (!strcmp(atemp->e_ext.number, e_ext.number))
892 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
893 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
894 return; /* must exit here */
897 /* FALL THROUGH !!!! */
898 case INFO_ITYPE_VBOX:
899 /* get dialed extension's info */
900 // SCPY(exten, e_dialinginfo.id);
901 // if (strchr(exten, ','))
902 // *strchr(exten, ',') = '\0';
903 // if (!read_extension(&e_ext, exten))
904 if (!read_extension(&e_ext, e_dialinginfo.id))
906 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
907 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
908 return; /* must exit here */
911 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
913 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
918 /* string from unconditional call forward (cfu) */
922 /* present to forwarded party */
923 if (e_ext.anon_ignore && e_callerinfo.id[0])
925 e_callerinfo.present = INFO_PRESENT_ALLOWED;
927 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
931 /* string from busy call forward (cfb) */
935 class EndpointAppPBX *checkapp = apppbx_first;
938 if (checkapp != this) /* any other endpoint except our own */
940 if (!strcmp(checkapp->e_ext.number, e_ext.number))
942 /* present to forwarded party */
943 if (e_ext.anon_ignore && e_callerinfo.id[0])
945 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))
951 checkapp = checkapp->next;
955 /* string from no-response call forward (cfnr) */
959 /* when cfnr is done, out_setup() will setup the call */
962 /* present to forwarded party */
963 if (e_ext.anon_ignore && e_callerinfo.id[0])
965 e_callerinfo.present = INFO_PRESENT_ALLOWED;
969 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
971 e_cfnr_release = now + e_ext.cfnr_delay;
972 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
973 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);
977 /* call to all internal interfaces */
978 p = e_ext.interfaces;
979 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
983 while(*p!=',' && *p!='\0')
988 /* found interface */
989 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
990 /* hunt for mISDNport and create Port */
991 mISDNport = hunt_port(ifname, &channel);
994 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
995 add_trace("interface", NULL, "%s", ifname);
999 /* creating INTERNAL port */
1000 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1001 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force);
1003 FATAL("No memory for DSS1 Port instance\n");
1004 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1005 memset(&dialinginfo, 0, sizeof(dialinginfo));
1006 SCPY(dialinginfo.id, e_dialinginfo.id);
1007 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1008 dialinginfo.ntype = e_dialinginfo.ntype;
1009 /* create port_list relation */
1010 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1013 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1015 goto check_anycall_intern;
1017 /* directory.list */
1018 if (e_callerinfo.id[0] && (e_ext.centrex || e_ext.display_name))
1020 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1022 SCPY(e_callerinfo.name, dirname);
1024 // dss1 = (class Pdss1 *)port;
1026 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1027 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1028 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1029 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1030 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1031 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1032 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1033 //terminal if (e_dialinginfo.id)
1034 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1035 /* handle restricted caller ids */
1036 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);
1037 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);
1038 /* display callerid if desired for extension */
1039 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));
1040 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1041 /* use cnip, if enabld */
1043 message->param.setup.callerinfo.name[0] = '\0';
1044 /* screen clip if prefix is required */
1045 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1047 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1048 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
1049 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1051 /* use internal caller id */
1052 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1054 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1055 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1057 message_put(message);
1058 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1062 /* string from parallel call forward (cfp) */
1066 if (e_ext.anon_ignore && e_callerinfo.id[0])
1068 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1072 vbox_only: /* entry point for answering machine only */
1073 cfu_only: /* entry point for cfu */
1074 cfb_only: /* entry point for cfb */
1075 cfnr_only: /* entry point for cfnr */
1076 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1081 /* only if vbox should be dialed, and terminal is given */
1082 if (!strcmp(p, "vbox") && e_ext.number[0])
1084 /* go to the end of p */
1087 /* answering vbox call */
1088 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1090 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1091 FATAL("No memory for VBOX Port instance\n");
1092 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1093 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1097 while(*p!=',' && *p!='\0')
1102 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1103 /* hunt for mISDNport and create Port */
1104 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1107 /* creating EXTERNAL port*/
1108 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1109 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)))
1110 FATAL("No memory for DSS1 Port instance\n");
1111 earlyb = mISDNport->earlyb;
1115 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1116 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1122 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1123 goto check_anycall_intern;
1125 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1126 memset(&dialinginfo, 0, sizeof(dialinginfo));
1127 SCPY(dialinginfo.id, cfp);
1128 dialinginfo.itype = INFO_ITYPE_ISDN;
1129 dialinginfo.ntype = e_dialinginfo.ntype;
1130 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1133 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1135 goto check_anycall_intern;
1137 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1138 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1139 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1140 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1141 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1142 /* if clip is hidden */
1143 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1145 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1146 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1147 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1148 message->param.setup.callerinfo.present = e_ext.callerid_present;
1150 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1151 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1152 //terminal if (e_dialinginfo.id)
1153 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1154 /* handle restricted caller ids */
1155 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);
1156 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);
1157 /* display callerid if desired for extension */
1158 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));
1159 message_put(message);
1160 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1164 check_anycall_intern:
1165 /* now we have all ports created */
1168 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1170 if (!ea_endpoint->ep_join_id)
1172 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1173 return; /* must exit here */
1177 /* *********************** external call */
1179 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1180 /* call to extenal interfaces */
1181 p = e_dialinginfo.id;
1185 while(*p!=',' && *p!='\0')
1186 SCCAT(number, *p++);
1190 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");
1191 /* hunt for mISDNport and create Port */
1192 /* hunt for mISDNport and create Port */
1193 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1196 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1197 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1199 goto check_anycall_extern;
1201 /* creating EXTERNAL port*/
1202 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1203 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)))
1204 FATAL("No memory for DSS1 Port instance\n");
1205 earlyb = mISDNport->earlyb;
1206 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1207 memset(&dialinginfo, 0, sizeof(dialinginfo));
1208 SCPY(dialinginfo.id, number);
1209 dialinginfo.itype = INFO_ITYPE_ISDN;
1210 dialinginfo.ntype = e_dialinginfo.ntype;
1211 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1214 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1216 goto check_anycall_extern;
1218 // dss1 = (class Pdss1 *)port;
1219 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1220 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1221 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1222 SCPY(message->param.setup.dialinginfo.id, number);
1223 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1224 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1225 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1226 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1227 //terminal if (e_dialinginfo.id)
1228 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1229 /* handle restricted caller ids */
1230 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);
1231 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);
1232 /* display callerid if desired for extension */
1233 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));
1234 message_put(message);
1235 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1239 check_anycall_extern:
1240 /* now we have all ports created */
1243 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1245 if (!ea_endpoint->ep_join_id)
1247 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1248 return; /* must exit here */
1256 /* handler for endpoint
1260 int EndpointAppPBX::handler(void)
1262 if (e_crypt_state!=CM_ST_NULL)
1267 /* process answering machine (play) handling */
1270 if (e_action->index == ACTION_VBOX_PLAY)
1273 /* process action timeout */
1274 if (e_action_timeout)
1275 if (now_d >= e_action_timeout)
1277 if (e_state!=EPOINT_STATE_CONNECT)
1280 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1281 e_multipoint_cause = 0;
1282 e_multipoint_location = 0;
1283 new_state(EPOINT_STATE_IN_OVERLAP);
1286 return(1); /* we must exit, because our endpoint might be gone */
1288 e_action_timeout = 0;
1291 /* process action timeout */
1292 if (e_match_timeout)
1293 if (now_d >= e_match_timeout)
1296 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1298 return(1); /* we must exit, because our endpoint might be gone */
1303 /* process redialing (epoint redials to port) */
1306 if (now_d >= e_redial)
1309 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1311 new_state(EPOINT_STATE_OUT_SETUP);
1312 /* call special setup routine */
1319 /* process powerdialing (epoint redials to epoint) */
1320 if (e_powerdialing > 0)
1322 if (now_d >= e_powerdialing)
1324 e_powerdialing = -1; /* leave power dialing on */
1325 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1328 e_ruleset = ruleset_main;
1330 e_rule = e_ruleset->rule_first;
1332 new_state(EPOINT_STATE_IN_OVERLAP);
1338 /* process call forward no response */
1341 struct port_list *portlist;
1342 struct message *message;
1344 if (now >= e_cfnr_release)
1346 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1349 /* release all ports */
1350 while((portlist = ea_endpoint->ep_portlist))
1352 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1353 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1354 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1355 message_put(message);
1356 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1357 ea_endpoint->free_portlist(portlist);
1360 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1361 message->param.audiopath = CHANNEL_STATE_HOLD;
1362 message_put(message);
1363 /* indicate no patterns */
1364 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1365 message_put(message);
1366 /* set setup state, since we have no response from the new join */
1367 new_state(EPOINT_STATE_OUT_SETUP);
1372 if (now >= e_cfnr_call)
1374 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1380 /* handle connection to user */
1381 if (e_state == EPOINT_STATE_IDLE)
1383 /* epoint is idle, check callback */
1385 if (now_d >= e_callback)
1387 e_callback = 0; /* done with callback */
1388 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1389 new_state(EPOINT_STATE_OUT_SETUP);
1395 /* check for password timeout */
1397 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1399 struct port_list *portlist;
1401 if (now >= e_password_timeout)
1403 e_ruleset = ruleset_main;
1405 e_rule = e_ruleset->rule_first;
1407 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1408 trace_header("PASSWORD timeout", DIRECTION_NONE);
1410 e_connectedmode = 0;
1412 new_state(EPOINT_STATE_OUT_DISCONNECT);
1413 portlist = ea_endpoint->ep_portlist;
1416 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1417 set_tone(portlist, "cause_10");
1427 /* doing a hookflash */
1428 void EndpointAppPBX::hookflash(void)
1432 /* be sure that we are active */
1434 e_tx_state = NOTIFY_STATE_ACTIVE;
1436 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1438 if (ea_endpoint->ep_use > 1)
1440 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1443 /* dialtone after pressing the hash key */
1444 process_hangup(e_join_cause, e_join_location);
1445 e_multipoint_cause = 0;
1446 e_multipoint_location = 0;
1447 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1450 port->set_echotest(0);
1452 if (ea_endpoint->ep_join_id)
1454 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1456 e_ruleset = ruleset_main;
1458 e_rule = e_ruleset->rule_first;
1460 new_state(EPOINT_STATE_IN_OVERLAP);
1461 e_connectedmode = 1;
1462 SCPY(e_dialinginfo.id, e_ext.prefix);
1463 e_extdialing = e_dialinginfo.id;
1465 if (e_dialinginfo.id[0])
1467 set_tone(ea_endpoint->ep_portlist, "dialing");
1471 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1478 /* messages from port
1480 /* port MESSAGE_SETUP */
1481 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1483 struct message *message;
1485 int writeext; /* flags need to write extension after modification */
1487 struct interface *interface;
1489 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1491 portlist->port_type = param->setup.port_type;
1492 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1493 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1494 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1495 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1496 e_dtmf = param->setup.dtmf;
1497 /* screen incoming caller id */
1498 interface = interface_first;
1501 if (!strcmp(e_callerinfo.interface, interface->name))
1505 interface = interface->next;
1508 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1510 /* process extension */
1511 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1513 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1514 /* port makes call from extension */
1515 SCPY(e_callerinfo.extension, e_callerinfo.id);
1516 SCPY(e_ext.number, e_callerinfo.extension);
1517 SCPY(e_extension_interface, e_callerinfo.interface);
1520 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1523 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1525 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1527 /* get extension's info about caller */
1528 if (!read_extension(&e_ext, e_ext.number))
1530 /* extension doesn't exist */
1531 trace_header("EXTENSION (not created)", DIRECTION_IN);
1532 add_trace("extension", NULL, "%s", e_ext.number);
1534 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1535 new_state(EPOINT_STATE_OUT_DISCONNECT);
1536 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1537 e_ext.number[0] = '\0'; /* no terminal */
1542 /* put prefix (next) in front of e_dialinginfo.id */
1545 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1546 SCPY(e_dialinginfo.id, buffer);
1547 e_ext.next[0] = '\0';
1549 } else if (e_ext.prefix[0])
1551 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1552 SCPY(e_dialinginfo.id, buffer);
1555 /* screen caller id by extension's config */
1556 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1558 SCPY(e_callerinfo.name, e_ext.name);
1559 /* use caller id (or if exist: id_next_call) for this call */
1560 if (e_ext.id_next_call_present >= 0)
1562 SCPY(e_callerinfo.id, e_ext.id_next_call);
1563 /* if we restrict the pesentation */
1564 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1565 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1566 else e_callerinfo.present = e_ext.id_next_call_present;
1567 e_callerinfo.ntype = e_ext.id_next_call_type;
1568 e_ext.id_next_call_present = -1;
1572 SCPY(e_callerinfo.id, e_ext.callerid);
1573 /* if we restrict the pesentation */
1574 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1575 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1576 else e_callerinfo.present = e_ext.callerid_present;
1577 e_callerinfo.ntype = e_ext.callerid_type;
1580 /* extension is written */
1582 write_extension(&e_ext, e_ext.number);
1584 /* set volume of rx and tx */
1585 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1586 if (e_ext.txvol!=0 || e_ext.rxvol!=0)
1588 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1589 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1590 message->param.mISDNsignal.rxvol = e_ext.txvol;
1591 message->param.mISDNsignal.txvol = e_ext.rxvol;
1592 message_put(message);
1595 /* start recording if enabled */
1596 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1598 /* check if we are a terminal */
1599 if (e_ext.number[0] == '\0')
1600 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1603 port = find_port_id(portlist->port_id);
1605 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1610 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1611 /* no terminal identification */
1612 e_ext.number[0] = '\0';
1613 e_extension_interface[0] = '\0';
1614 memset(&e_ext, 0, sizeof(e_ext));
1615 e_ext.rights = 4; /* right to dial internat */
1619 e_ruleset = ruleset_main;
1621 e_rule = e_ruleset->rule_first;
1623 e_extdialing = e_dialinginfo.id;
1624 new_state(EPOINT_STATE_IN_SETUP);
1625 if (e_dialinginfo.id[0])
1627 set_tone(portlist, "dialing");
1630 if (e_ext.number[0])
1631 set_tone(portlist, "dialpbx");
1633 set_tone(portlist, "dialtone");
1636 if (e_state == EPOINT_STATE_IN_SETUP)
1638 /* request MORE info, if not already at higher state */
1639 new_state(EPOINT_STATE_IN_OVERLAP);
1640 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1641 message_put(message);
1642 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1646 /* port MESSAGE_INFORMATION */
1647 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1649 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1653 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1656 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1661 /* if vbox_play is done, the information are just used as they come */
1663 if (e_action->index == ACTION_VBOX_PLAY)
1665 /* concat dialing string */
1666 SCAT(e_dialinginfo.id, param->information.id);
1671 /* keypad when disconnect but in connected mode */
1672 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1674 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1675 /* processing keypad function */
1676 if (param->information.id[0] == '0')
1683 /* keypad when connected */
1684 if (e_state == EPOINT_STATE_CONNECT)
1688 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1689 /* processing keypad function */
1690 if (param->information.id[0] == '0')
1694 if (param->information.id[0])
1695 keypad_function(param->information.id[0]);
1698 if (e_ext.number[0])
1699 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1701 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1706 if (e_state != EPOINT_STATE_IN_OVERLAP)
1708 if (e_ext.number[0])
1709 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1711 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1715 if (!param->information.id[0])
1717 if (e_dialinginfo.id[0]=='\0' && !e_action)
1719 set_tone(portlist, "dialing");
1722 if (e_action->index==ACTION_OUTDIAL
1723 || e_action->index==ACTION_EXTERNAL)
1726 set_tone(portlist, "dialing");
1727 else if (!e_extdialing[0])
1728 set_tone(portlist, "dialing");
1730 /* concat dialing string */
1731 SCAT(e_dialinginfo.id, param->information.id);
1735 /* port MESSAGE_DTMF */
1736 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1738 /* only if dtmf detection is enabled */
1741 trace_header("DTMF (disabled)", DIRECTION_IN);
1745 trace_header("DTMF", DIRECTION_IN);
1746 add_trace("digit", NULL, "%c", param->dtmf);
1750 NOTE: vbox is now handled due to overlap state
1751 /* if vbox_play is done, the dtmf digits are just used as they come */
1753 if (e_action->index == ACTION_VBOX_PLAY)
1755 /* concat dialing string */
1756 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1758 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1759 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1762 /* continue to process *X# sequences */
1766 /* check for *X# sequence */
1767 if (e_state == EPOINT_STATE_CONNECT)
1769 if (e_dtmf_time+3 < now)
1771 /* the last digit was too far in the past to be a sequence */
1772 if (param->dtmf == '*')
1773 /* only start is allowed in the sequence */
1779 /* we have a sequence of digits, see what we got */
1780 if (param->dtmf == '*')
1782 else if (param->dtmf>='0' && param->dtmf<='9')
1784 /* we need to have a star before we receive the digit of the sequence */
1785 if (e_dtmf_last == '*')
1786 e_dtmf_last = param->dtmf;
1787 } else if (param->dtmf == '#')
1790 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1792 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1793 if (e_dtmf_last == '0')
1798 /* processing keypad function */
1800 keypad_function(e_dtmf_last);
1806 /* set last time of dtmf */
1811 /* check for ## hookflash during dialing */
1813 if (e_action->index==ACTION_PASSWORD
1814 || e_action->index==ACTION_PASSWORD_WRITE)
1816 if (param->dtmf=='#') /* current digit is '#' */
1818 if (e_state==EPOINT_STATE_IN_DISCONNECT
1819 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1836 /* dialing using dtmf digit */
1837 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1839 if (e_dialinginfo.id[0]=='\0' && !e_action)
1841 set_tone(portlist, "dialing");
1843 /* concat dialing string */
1844 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1846 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1847 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1853 /* port MESSAGE_CRYPT */
1854 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1856 /* send crypt response to cryptman */
1857 if (param->crypt.type == CR_MESSAGE_IND)
1858 cryptman_msg2man(param->crypt.data, param->crypt.len);
1860 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1863 /* port MESSAGE_OVERLAP */
1864 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1866 struct message *message;
1868 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1870 /* signal to call tool */
1871 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1873 if (e_dialing_queue[0] && portlist)
1875 /* send what we have not dialed yet, because we had no setup complete */
1876 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1877 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1878 SCPY(message->param.information.id, e_dialing_queue);
1879 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1880 message_put(message);
1881 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1882 e_dialing_queue[0] = '\0';
1884 /* check if pattern is available */
1885 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
1887 /* indicate patterns */
1888 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1889 message_put(message);
1891 /* connect audio, if not already */
1892 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1893 message->param.audiopath = CHANNEL_STATE_CONNECT;
1894 message_put(message);
1897 /* indicate no patterns */
1898 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1899 message_put(message);
1901 /* disconnect audio, if not already */
1902 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1903 message->param.audiopath = CHANNEL_STATE_HOLD;
1904 message_put(message);
1906 new_state(EPOINT_STATE_OUT_OVERLAP);
1907 /* if we are in a join */
1908 if (ea_endpoint->ep_join_id)
1910 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1911 memcpy(&message->param, param, sizeof(union parameter));
1912 message_put(message);
1916 /* port MESSAGE_PROCEEDING */
1917 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1919 struct message *message;
1921 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1923 /* signal to call tool */
1924 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1926 e_state = EPOINT_STATE_OUT_PROCEEDING;
1927 /* check if pattern is availatle */
1928 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1930 /* indicate patterns */
1931 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1932 message_put(message);
1934 /* connect audio, if not already */
1935 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1936 message->param.audiopath = CHANNEL_STATE_CONNECT;
1937 message_put(message);
1940 /* indicate no patterns */
1941 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1942 message_put(message);
1944 /* disconnect audio, if not already */
1945 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1946 message->param.audiopath = CHANNEL_STATE_HOLD;
1947 message_put(message);
1949 /* if we are in a call */
1950 if (ea_endpoint->ep_join_id)
1952 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1953 memcpy(&message->param, param, sizeof(union parameter));
1954 message_put(message);
1958 /* port MESSAGE_ALERTING */
1959 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1961 struct message *message;
1963 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1965 /* signal to call tool */
1966 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1968 new_state(EPOINT_STATE_OUT_ALERTING);
1969 /* check if pattern is available */
1970 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1972 /* indicate patterns */
1973 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1974 message_put(message);
1976 /* connect audio, if not already */
1977 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1978 message->param.audiopath = CHANNEL_STATE_CONNECT;
1979 message_put(message);
1982 /* indicate no patterns */
1983 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1984 message_put(message);
1986 /* disconnect audio, if not already */
1987 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1988 message->param.audiopath = CHANNEL_STATE_HOLD;
1989 message_put(message);
1991 /* if we are in a call */
1992 if (ea_endpoint->ep_join_id)
1994 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1995 memcpy(&message->param, param, sizeof(union parameter));
1996 message_put(message);
2000 /* port MESSAGE_CONNECT */
2001 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2003 struct message *message;
2005 unsigned long port_id = portlist->port_id;
2006 struct port_list *tportlist;
2008 struct interface *interface;
2010 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2012 /* signal to call tool */
2013 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2015 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2016 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2017 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2019 tportlist = ea_endpoint->ep_portlist;
2020 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2021 tportlist = tportlist->next;
2022 if (tportlist->port_id == port_id)
2023 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2024 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2025 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2026 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2027 message_put(message);
2028 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2029 ea_endpoint->free_portlist(tportlist);
2031 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2035 /* screen incoming connected id */
2036 interface = interface_first;
2039 if (!strcmp(e_connectinfo.interface, interface->name))
2043 interface = interface->next;
2046 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2048 /* screen connected name */
2050 SCPY(e_connectinfo.name, e_ext.name);
2052 /* add internal id to colp */
2053 SCPY(e_connectinfo.extension, e_ext.number);
2055 /* we store the connected port number */
2056 SCPY(e_extension_interface, e_connectinfo.interface);
2058 /* for internal and am calls, we get the extension's id */
2059 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2061 SCPY(e_connectinfo.id, e_ext.callerid);
2062 SCPY(e_connectinfo.extension, e_ext.number);
2063 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2064 e_connectinfo.ntype = e_ext.callerid_type;
2065 e_connectinfo.present = e_ext.callerid_present;
2067 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2069 e_connectinfo.itype = INFO_ITYPE_VBOX;
2070 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2073 new_state(EPOINT_STATE_CONNECT);
2075 /* set volume of rx and tx */
2076 if (e_ext.txvol!=0 || e_ext.rxvol!=0)
2078 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2079 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2080 message->param.mISDNsignal.rxvol = e_ext.txvol;
2081 message->param.mISDNsignal.txvol = e_ext.rxvol;
2082 message_put(message);
2085 e_cfnr_call = e_cfnr_release = 0;
2086 if (e_ext.number[0])
2087 e_dtmf = 1; /* allow dtmf */
2090 /* other calls with no caller id (or not available for the extension) and force colp */
2091 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2093 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2094 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2096 port = find_port_id(portlist->port_id);
2099 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype));
2100 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2105 /* send connect to join */
2106 if (ea_endpoint->ep_join_id)
2108 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2109 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2110 message_put(message);
2112 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2113 message->param.audiopath = CHANNEL_STATE_CONNECT;
2114 message_put(message);
2115 } else if (!e_adminid)
2118 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2119 SCPY(e_ext.number, e_cbcaller);
2120 new_state(EPOINT_STATE_IN_OVERLAP);
2121 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2123 /* get extension's info about terminal */
2124 if (!read_extension(&e_ext, e_ext.number))
2126 /* extension doesn't exist */
2127 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2128 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2129 new_state(EPOINT_STATE_OUT_DISCONNECT);
2130 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2134 /* put prefix in front of e_cbdialing */
2135 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2136 SCPY(e_dialinginfo.id, buffer);
2137 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2138 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2140 /* use caller id (or if exist: id_next_call) for this call */
2141 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2142 SCPY(e_callerinfo.extension, e_ext.number);
2143 if (e_ext.id_next_call_present >= 0)
2145 SCPY(e_callerinfo.id, e_ext.id_next_call);
2146 e_callerinfo.present = e_ext.id_next_call_present;
2147 e_callerinfo.ntype = e_ext.id_next_call_type;
2148 e_ext.id_next_call_present = -1;
2149 /* extension is written */
2150 write_extension(&e_ext, e_ext.number);
2153 SCPY(e_callerinfo.id, e_ext.callerid);
2154 e_callerinfo.present = e_ext.callerid_present;
2155 e_callerinfo.ntype = e_ext.callerid_type;
2158 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2161 /* check if caller id is NOT authenticated */
2162 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2164 /* make call state to enter password */
2165 new_state(EPOINT_STATE_IN_OVERLAP);
2166 e_action = &action_password_write;
2167 e_match_timeout = 0;
2168 e_match_to_action = NULL;
2169 e_dialinginfo.id[0] = '\0';
2170 e_extdialing = strchr(e_dialinginfo.id, '\0');
2171 e_password_timeout = now+20;
2175 /* incoming call (callback) */
2176 e_ruleset = ruleset_main;
2178 e_rule = e_ruleset->rule_first;
2180 e_extdialing = e_dialinginfo.id;
2181 if (e_dialinginfo.id[0])
2183 set_tone(portlist, "dialing");
2187 set_tone(portlist, "dialpbx");
2190 } else /* testcall */
2192 set_tone(portlist, "hold");
2195 /* start recording if enabled, not when answering machine answers */
2196 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))
2198 /* check if we are a terminal */
2199 if (e_ext.number[0] == '\0')
2200 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2203 port = find_port_id(portlist->port_id);
2205 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2210 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2211 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2213 struct message *message;
2215 unsigned long port_id = portlist->port_id;
2219 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2221 /* signal to call tool */
2222 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2224 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2225 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2227 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2232 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);
2233 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2234 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2236 /* check if we have more than one portlist relation and we just ignore the disconnect */
2237 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2239 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2240 portlist = ea_endpoint->ep_portlist;
2243 if (portlist->port_id == port_id)
2245 portlist = portlist->next;
2248 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2249 if (message_type != MESSAGE_RELEASE)
2251 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2252 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2253 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2254 message_put(message);
2255 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2257 ea_endpoint->free_portlist(portlist);
2258 return; /* one relation removed */
2260 if (e_state == EPOINT_STATE_CONNECT)
2262 /* use cause from port after connect */
2263 cause = param->disconnectinfo.cause;
2264 location = param->disconnectinfo.location;
2267 /* use multipoint cause if no connect yet */
2268 if (e_multipoint_cause)
2270 cause = e_multipoint_cause;
2271 location = e_multipoint_location;
2274 cause = CAUSE_NOUSER;
2275 location = LOCATION_PRIVATE_LOCAL;
2279 e_cfnr_call = e_cfnr_release = 0;
2281 /* process hangup */
2282 process_hangup(e_join_cause, e_join_location);
2283 e_multipoint_cause = 0;
2284 e_multipoint_location = 0;
2286 if (message_type == MESSAGE_DISCONNECT)
2288 /* tone to disconnected end */
2289 SPRINT(buffer, "cause_%02x", cause);
2290 if (ea_endpoint->ep_portlist)
2291 set_tone(ea_endpoint->ep_portlist, buffer);
2293 new_state(EPOINT_STATE_IN_DISCONNECT);
2296 if (ea_endpoint->ep_join_id)
2298 int haspatterns = 0;
2299 /* check if pattern is available */
2300 if (ea_endpoint->ep_portlist)
2301 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2302 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
2303 && message_type != MESSAGE_RELEASE) // if we release, we are done
2307 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2308 /* indicate patterns */
2309 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2310 message_put(message);
2311 /* connect audio, if not already */
2312 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2313 message->param.audiopath = CHANNEL_STATE_CONNECT;
2314 message_put(message);
2315 /* send disconnect */
2316 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2317 memcpy(&message->param, param, sizeof(union parameter));
2318 message_put(message);
2319 /* disable encryption if disconnected */
2320 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2322 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2326 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2329 if (message_type == MESSAGE_RELEASE)
2330 ea_endpoint->free_portlist(portlist);
2331 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2332 return; /* must exit here */
2335 /* port MESSAGE_TIMEOUT */
2336 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2340 trace_header("TIMEOUT", DIRECTION_IN);
2341 message_type = MESSAGE_DISCONNECT;
2342 switch (param->state)
2344 case PORT_STATE_OUT_SETUP:
2345 case PORT_STATE_OUT_OVERLAP:
2346 add_trace("state", NULL, "outgoing setup/dialing");
2348 /* no user responding */
2349 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2350 return; /* must exit here */
2352 case PORT_STATE_IN_SETUP:
2353 case PORT_STATE_IN_OVERLAP:
2354 add_trace("state", NULL, "incoming setup/dialing");
2355 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2356 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2359 case PORT_STATE_OUT_PROCEEDING:
2360 add_trace("state", NULL, "outgoing proceeding");
2362 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2363 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2364 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2365 return; /* must exit here */
2367 case PORT_STATE_IN_PROCEEDING:
2368 add_trace("state", NULL, "incoming proceeding");
2369 param->disconnectinfo.cause = CAUSE_NOUSER;
2370 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2373 case PORT_STATE_OUT_ALERTING:
2374 add_trace("state", NULL, "outgoing alerting");
2376 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2377 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2378 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2379 return; /* must exit here */
2381 case PORT_STATE_CONNECT:
2382 add_trace("state", NULL, "connect");
2384 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2385 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2386 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2387 return; /* must exit here */
2389 case PORT_STATE_IN_ALERTING:
2390 add_trace("state", NULL, "incoming alerting");
2391 param->disconnectinfo.cause = CAUSE_NOANSWER;
2392 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2395 case PORT_STATE_IN_DISCONNECT:
2396 case PORT_STATE_OUT_DISCONNECT:
2397 add_trace("state", NULL, "disconnect");
2399 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2400 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2401 return; /* must exit here */
2404 param->disconnectinfo.cause = 31; /* normal unspecified */
2405 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2408 /* release call, disconnect isdn */
2410 new_state(EPOINT_STATE_OUT_DISCONNECT);
2411 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2412 SCPY(e_tone, cause);
2415 set_tone(portlist, cause);
2416 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2417 portlist = portlist->next;
2419 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2422 /* port MESSAGE_NOTIFY */
2423 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2425 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2427 struct message *message;
2431 /* signal to call tool */
2432 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2433 if (param->notifyinfo.notify)
2435 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2438 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2439 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2441 case INFO_NOTIFY_REMOTE_HOLD:
2442 case INFO_NOTIFY_USER_SUSPENDED:
2443 /* tell call about it */
2444 if (ea_endpoint->ep_join_id)
2446 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2447 message->param.audiopath = CHANNEL_STATE_HOLD;
2448 message_put(message);
2452 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2453 case INFO_NOTIFY_USER_RESUMED:
2454 /* set volume of rx and tx */
2455 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2456 if (e_ext.txvol!=0 || e_ext.rxvol!=0)
2459 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2460 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2461 message->param.mISDNsignal.rxvol = e_ext.txvol;
2462 message->param.mISDNsignal.txvol = e_ext.rxvol;
2463 message_put(message);
2465 /* set current tone */
2467 set_tone(portlist, e_tone);
2468 /* tell call about it */
2469 if (ea_endpoint->ep_join_id)
2471 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2472 message->param.audiopath = CHANNEL_STATE_CONNECT;
2473 message_put(message);
2478 /* get name of notify */
2479 switch(param->notifyinfo.notify)
2485 logtext = "USER_SUSPENDED";
2488 logtext = "BEARER_SERVICE_CHANGED";
2491 logtext = "USER_RESUMED";
2494 logtext = "CONFERENCE_ESTABLISHED";
2497 logtext = "CONFERENCE_DISCONNECTED";
2500 logtext = "OTHER_PARTY_ADDED";
2503 logtext = "ISOLATED";
2506 logtext = "REATTACHED";
2509 logtext = "OTHER_PARTY_ISOLATED";
2512 logtext = "OTHER_PARTY_REATTACHED";
2515 logtext = "OTHER_PARTY_SPLIT";
2518 logtext = "OTHER_PARTY_DISCONNECTED";
2521 logtext = "CONFERENCE_FLOATING";
2524 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2527 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2530 logtext = "CALL_IS_A_WAITING_CALL";
2533 logtext = "DIVERSION_ACTIVATED";
2536 logtext = "RESERVED_CT_1";
2539 logtext = "RESERVED_CT_2";
2542 logtext = "REVERSE_CHARGING";
2545 logtext = "REMOTE_HOLD";
2548 logtext = "REMOTE_RETRIEVAL";
2551 logtext = "CALL_IS_DIVERTING";
2554 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2559 /* notify call if available */
2560 if (ea_endpoint->ep_join_id)
2562 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2563 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2564 message_put(message);
2569 /* port MESSAGE_FACILITY */
2570 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2572 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2574 struct message *message;
2576 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2577 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2578 message_put(message);
2581 /* port MESSAGE_SUSPEND */
2582 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2583 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2585 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2587 /* epoint is now parked */
2588 ea_endpoint->ep_park = 1;
2589 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2590 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2592 /* remove port relation */
2593 ea_endpoint->free_portlist(portlist);
2596 /* port MESSAGE_RESUME */
2597 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2598 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2600 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2602 /* epoint is now resumed */
2603 ea_endpoint->ep_park = 0;
2608 /* port sends message to the endpoint
2610 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2612 struct port_list *portlist;
2613 struct message *message;
2615 portlist = ea_endpoint->ep_portlist;
2618 if (port_id == portlist->port_id)
2620 portlist = portlist->next;
2624 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);
2628 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2629 switch(message_type)
2631 case MESSAGE_DATA: /* data from port */
2632 /* check if there is a call */
2633 if (!ea_endpoint->ep_join_id)
2635 /* continue if only one portlist */
2636 if (ea_endpoint->ep_portlist->next != NULL)
2638 /* forward message */
2639 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2642 case MESSAGE_TONE_EOF: /* tone is end of file */
2643 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2646 if (e_action->index == ACTION_VBOX_PLAY)
2650 if (e_action->index == ACTION_EFI)
2657 case MESSAGE_TONE_COUNTER: /* counter info received */
2658 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);
2660 if (e_action->index == ACTION_VBOX_PLAY)
2662 e_vbox_counter = param->counter.current;
2663 if (param->counter.max >= 0)
2664 e_vbox_counter_max = param->counter.max;
2668 /* PORT sends SETUP message */
2670 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);
2671 if (e_state!=EPOINT_STATE_IDLE)
2673 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2676 port_setup(portlist, message_type, param);
2679 /* PORT sends INFORMATION message */
2680 case MESSAGE_INFORMATION: /* additional digits received */
2681 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);
2682 port_information(portlist, message_type, param);
2685 /* PORT sends FACILITY message */
2686 case MESSAGE_FACILITY:
2687 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2688 port_facility(portlist, message_type, param);
2691 /* PORT sends DTMF message */
2692 case MESSAGE_DTMF: /* dtmf digits received */
2693 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);
2694 port_dtmf(portlist, message_type, param);
2697 /* PORT sends CRYPT message */
2698 case MESSAGE_CRYPT: /* crypt response received */
2699 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2700 port_crypt(portlist, message_type, param);
2703 /* PORT sends MORE message */
2704 case MESSAGE_OVERLAP:
2705 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);
2706 if (e_state != EPOINT_STATE_OUT_SETUP)
2708 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);
2711 port_overlap(portlist, message_type, param);
2714 /* PORT sends PROCEEDING message */
2715 case MESSAGE_PROCEEDING: /* port is proceeding */
2716 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);
2717 if (e_state!=EPOINT_STATE_OUT_SETUP
2718 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2720 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);
2723 port_proceeding(portlist, message_type, param);
2726 /* PORT sends ALERTING message */
2727 case MESSAGE_ALERTING:
2728 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);
2729 if (e_state!=EPOINT_STATE_OUT_SETUP
2730 && e_state!=EPOINT_STATE_OUT_OVERLAP
2731 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2733 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);
2736 port_alerting(portlist, message_type, param);
2739 /* PORT sends CONNECT message */
2740 case MESSAGE_CONNECT:
2741 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);
2742 if (e_state!=EPOINT_STATE_OUT_SETUP
2743 && e_state!=EPOINT_STATE_OUT_OVERLAP
2744 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2745 && e_state!=EPOINT_STATE_OUT_ALERTING)
2747 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2750 port_connect(portlist, message_type, param);
2753 /* PORT sends DISCONNECT message */
2754 case MESSAGE_DISCONNECT: /* port is disconnected */
2755 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);
2756 port_disconnect_release(portlist, message_type, param);
2759 /* PORT sends a RELEASE message */
2760 case MESSAGE_RELEASE: /* port releases */
2761 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);
2762 /* portlist is release at port_disconnect_release, thanx Paul */
2763 port_disconnect_release(portlist, message_type, param);
2766 /* PORT sends a TIMEOUT message */
2767 case MESSAGE_TIMEOUT:
2768 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);
2769 port_timeout(portlist, message_type, param);
2770 break; /* release */
2772 /* PORT sends a NOTIFY message */
2773 case MESSAGE_NOTIFY:
2774 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);
2775 port_notify(portlist, message_type, param);
2778 /* PORT sends a SUSPEND message */
2779 case MESSAGE_SUSPEND:
2780 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);
2781 port_suspend(portlist, message_type, param);
2782 break; /* suspend */
2784 /* PORT sends a RESUME message */
2785 case MESSAGE_RESUME:
2786 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);
2787 port_resume(portlist, message_type, param);
2791 /* port assigns bchannel */
2792 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2793 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);
2794 /* only one port is expected to be connected to bchannel */
2795 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2796 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2802 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);
2805 /* Note: this endpoint may be destroyed, so we MUST return */
2809 /* messages from join
2811 /* join MESSAGE_CRYPT */
2812 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2814 switch(param->crypt.type)
2816 /* message from remote port to "crypt manager" */
2817 case CU_ACTK_REQ: /* activate key-exchange */
2818 case CU_ACTS_REQ: /* activate shared key */
2819 case CU_DACT_REQ: /* deactivate */
2820 case CU_INFO_REQ: /* request last info message */
2821 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2824 /* message from "crypt manager" to user */
2825 case CU_ACTK_CONF: /* key-echange done */
2826 case CU_ACTS_CONF: /* shared key done */
2827 case CU_DACT_CONF: /* deactivated */
2828 case CU_DACT_IND: /* deactivated */
2829 case CU_ERROR_IND: /* receive error message */
2830 case CU_INFO_IND: /* receive info message */
2831 case CU_INFO_CONF: /* receive info message */
2832 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2836 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);
2840 /* join MESSAGE_INFORMATION */
2841 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2843 struct message *message;
2849 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2850 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2851 message_put(message);
2852 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2853 portlist = portlist->next;
2857 /* join MESSAGE_FACILITY */
2858 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2860 struct message *message;
2862 if (!e_ext.facility)
2869 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2870 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2871 message_put(message);
2872 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2873 portlist = portlist->next;
2877 /* join MESSAGE_MORE */
2878 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2880 struct message *message;
2882 new_state(EPOINT_STATE_IN_OVERLAP);
2885 if (e_join_pattern && e_ext.own_setup)
2887 /* disconnect audio */
2888 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2889 message->param.audiopath = CHANNEL_STATE_HOLD;
2890 message_put(message);
2892 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2894 set_tone(portlist, "dialtone");
2897 if (e_ext.number[0])
2898 set_tone(portlist, "dialpbx");
2900 set_tone(portlist, "dialtone");
2903 /* join MESSAGE_PROCEEDING */
2904 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2906 struct message *message;
2908 new_state(EPOINT_STATE_IN_PROCEEDING);
2910 /* own proceeding tone */
2913 /* connect / disconnect audio */
2914 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2915 if (e_ext.own_proceeding)
2916 message->param.audiopath = CHANNEL_STATE_HOLD;
2918 message->param.audiopath = CHANNEL_STATE_CONNECT;
2919 message_put(message);
2921 // UCPY(e_join_tone, "proceeding");
2924 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2925 message_put(message);
2926 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2928 set_tone(portlist, "proceeding");
2931 /* join MESSAGE_ALERTING */
2932 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2934 struct message *message;
2936 new_state(EPOINT_STATE_IN_ALERTING);
2938 /* own alerting tone */
2941 /* connect / disconnect audio */
2942 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2943 if (e_ext.own_alerting)
2944 message->param.audiopath = CHANNEL_STATE_HOLD;
2946 message->param.audiopath = CHANNEL_STATE_CONNECT;
2947 message_put(message);
2951 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2952 message_put(message);
2953 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2955 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2957 set_tone(portlist, "ringing");
2960 if (e_ext.number[0])
2961 set_tone(portlist, "ringpbx");
2963 set_tone(portlist, "ringing");
2966 /* join MESSAGE_CONNECT */
2967 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2969 struct message *message;
2971 new_state(EPOINT_STATE_CONNECT);
2972 // UCPY(e_join_tone, "");
2973 if (e_ext.number[0])
2974 e_dtmf = 1; /* allow dtmf */
2976 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2979 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2980 memcpy(&message->param, param, sizeof(union parameter));
2982 /* screen clip if prefix is required */
2983 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
2985 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2986 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
2987 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2990 /* use internal caller id */
2991 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
2993 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2994 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2997 /* handle restricted caller ids */
2998 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);
2999 /* display callerid if desired for extension */
3000 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));
3002 /* use conp, if enabld */
3004 message->param.connectinfo.name[0] = '\0';
3007 message_put(message);
3008 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3010 set_tone(portlist, NULL);
3012 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3013 message->param.audiopath = CHANNEL_STATE_CONNECT;
3014 message_put(message);
3018 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3019 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3022 struct message *message;
3023 struct port_list *portlist = NULL;
3026 /* be sure that we are active */
3028 e_tx_state = NOTIFY_STATE_ACTIVE;
3030 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3031 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3033 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3035 /* set time for power dialing */
3036 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3039 /* set redial tone */
3040 if (ea_endpoint->ep_portlist)
3044 set_tone(ea_endpoint->ep_portlist, "redial");
3045 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);
3046 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3047 if (e_state==EPOINT_STATE_IN_OVERLAP)
3049 new_state(EPOINT_STATE_IN_PROCEEDING);
3050 if (ea_endpoint->ep_portlist)
3052 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3053 message_put(message);
3054 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3056 /* caused the error, that the first knock sound was not there */
3057 /* set_tone(portlist, "proceeding"); */
3059 /* send display of powerdialing */
3060 if (e_ext.display_dialing)
3062 portlist = ea_endpoint->ep_portlist;
3065 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3067 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3069 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3070 message_put(message);
3071 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3072 portlist = portlist->next;
3081 if ((e_state!=EPOINT_STATE_CONNECT
3082 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3083 && e_state!=EPOINT_STATE_IN_OVERLAP
3084 && e_state!=EPOINT_STATE_IN_PROCEEDING
3085 && e_state!=EPOINT_STATE_IN_ALERTING)
3086 || !ea_endpoint->ep_portlist) /* or no port */
3088 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3089 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3090 return; /* must exit here */
3095 e_join_cause = param->disconnectinfo.cause;
3096 e_join_location = param->disconnectinfo.location;
3099 /* on release we need the audio again! */
3100 if (message_type == MESSAGE_RELEASE)
3103 ea_endpoint->ep_join_id = 0;
3105 /* disconnect and select tone */
3106 new_state(EPOINT_STATE_OUT_DISCONNECT);
3107 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3108 /* if own_cause, we must release the join */
3109 if (e_ext.own_cause /* own cause */
3110 || !e_join_pattern) /* no patterns */
3112 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);
3113 if (message_type != MESSAGE_RELEASE)
3114 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3116 } else /* else we enable audio */
3118 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3119 message->param.audiopath = CHANNEL_STATE_CONNECT;
3120 message_put(message);
3122 /* send disconnect message */
3123 SCPY(e_tone, cause);
3124 portlist = ea_endpoint->ep_portlist;
3127 set_tone(portlist, cause);
3128 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3129 portlist = portlist->next;
3133 /* join MESSAGE_SETUP */
3134 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3136 struct message *message;
3137 struct interface *interface;
3139 /* if we already in setup state, we just update the dialing with new digits */
3140 if (e_state == EPOINT_STATE_OUT_SETUP
3141 || e_state == EPOINT_STATE_OUT_OVERLAP)
3143 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3144 /* if digits changed, what we have already dialed */
3145 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3147 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);
3148 /* release all ports */
3149 while((portlist = ea_endpoint->ep_portlist))
3151 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3152 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3153 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3154 message_put(message);
3155 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3156 ea_endpoint->free_portlist(portlist);
3159 /* disconnect audio */
3160 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3161 message->param.audiopath = CHANNEL_STATE_HOLD;
3162 message_put(message);
3164 /* get dialing info */
3165 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3166 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3167 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3168 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3169 new_state(EPOINT_STATE_OUT_OVERLAP);
3172 e_redial = now_d + 1; /* set redial one second in the future */
3175 /* if we have a pending redial, so we just adjust the dialing number */
3178 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);
3179 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3182 if (!ea_endpoint->ep_portlist)
3184 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3186 if (ea_endpoint->ep_portlist->next)
3188 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3190 if (e_state == EPOINT_STATE_OUT_SETUP)
3193 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);
3194 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3198 /* get what we have not dialed yet */
3199 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));
3200 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3201 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3202 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3203 message_put(message);
3204 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3206 /* always store what we have dialed or queued */
3207 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3211 if (e_state != EPOINT_STATE_IDLE)
3213 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3216 /* if an internal extension is dialed, copy that number */
3217 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3218 SCPY(e_ext.number, param->setup.dialinginfo.id);
3219 /* if an internal extension is dialed, get extension's info about caller */
3220 if (e_ext.number[0])
3222 if (!read_extension(&e_ext, e_ext.number))
3224 e_ext.number[0] = '\0';
3225 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3229 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3230 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3231 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3232 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3234 /* process (voice over) data calls */
3235 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3237 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3238 memset(&e_capainfo, 0, sizeof(e_capainfo));
3239 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3240 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3241 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3244 new_state(EPOINT_STATE_OUT_SETUP);
3245 /* call special setup routine */
3249 /* join MESSAGE_mISDNSIGNAL */
3250 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3252 struct message *message;
3256 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3257 memcpy(&message->param, param, sizeof(union parameter));
3258 message_put(message);
3259 portlist = portlist->next;
3263 /* join MESSAGE_NOTIFY */
3264 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3266 struct message *message;
3269 if (param->notifyinfo.notify)
3271 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3272 // /* if notification was generated locally, we turn hold music on/off */
3273 // if (param->notifyinfo.local)
3274 // 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)
3279 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3281 if (!strcmp(e_tone, "hold")) // don't interrupt other tones
3285 set_tone(portlist, "");
3286 portlist = portlist->next;
3289 portlist = ea_endpoint->ep_portlist;
3294 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3298 set_tone(portlist, "hold");
3299 portlist = portlist->next;
3301 portlist = ea_endpoint->ep_portlist;
3306 /* save new state */
3307 e_tx_state = new_state;
3310 /* notify port(s) about it */
3313 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3314 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3315 /* handle restricted caller ids */
3316 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3317 /* display callerid if desired for extension */
3318 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));
3319 message_put(message);
3320 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3321 portlist = portlist->next;
3325 /* JOIN sends messages to the endpoint
3327 void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, union parameter *param)
3329 struct port_list *portlist;
3330 struct message *message;
3334 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3338 portlist = ea_endpoint->ep_portlist;
3340 /* send MESSAGE_DATA to port */
3341 if (message_type == MESSAGE_DATA)
3343 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3345 /* skip if no port relation */
3348 /* skip if more than one port relation */
3351 /* forward audio data to port */
3352 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3357 // 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);
3358 switch(message_type)
3360 /* JOIN SENDS TONE message */
3362 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);
3363 set_tone(portlist, param->tone.name);
3366 /* JOIN SENDS CRYPT message */
3368 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);
3369 join_crypt(portlist, message_type, param);
3372 /* JOIN sends INFORMATION message */
3373 case MESSAGE_INFORMATION:
3374 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);
3375 join_information(portlist, message_type, param);
3378 /* JOIN sends FACILITY message */
3379 case MESSAGE_FACILITY:
3380 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);
3381 join_facility(portlist, message_type, param);
3384 /* JOIN sends OVERLAP message */
3385 case MESSAGE_OVERLAP:
3386 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);
3387 if (e_state!=EPOINT_STATE_IN_SETUP
3388 && e_state!=EPOINT_STATE_IN_OVERLAP)
3390 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3393 join_overlap(portlist, message_type, param);
3396 /* JOIN sends PROCEEDING message */
3397 case MESSAGE_PROCEEDING:
3398 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);
3399 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3401 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3404 join_proceeding(portlist, message_type, param);
3407 /* JOIN sends ALERTING message */
3408 case MESSAGE_ALERTING:
3409 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);
3410 if (e_state!=EPOINT_STATE_IN_OVERLAP
3411 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3413 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3416 join_alerting(portlist, message_type, param);
3419 /* JOIN sends CONNECT message */
3420 case MESSAGE_CONNECT:
3421 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);
3422 if (e_state!=EPOINT_STATE_IN_OVERLAP
3423 && e_state!=EPOINT_STATE_IN_PROCEEDING
3424 && e_state!=EPOINT_STATE_IN_ALERTING)
3426 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3429 join_connect(portlist, message_type, param);
3432 /* JOIN sends DISCONNECT/RELEASE message */
3433 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3434 case MESSAGE_RELEASE: /* JOIN releases */
3435 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);
3436 join_disconnect_release(message_type, param);
3439 /* JOIN sends SETUP message */
3441 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);
3442 join_setup(portlist, message_type, param);
3445 /* JOIN sends special mISDNSIGNAL message */
3446 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3447 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);
3448 join_mISDNsignal(portlist, message_type, param);
3452 /* JOIN requests bchannel */
3453 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3454 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);
3455 /* only one port is expected to be connected to bchannel */
3462 set_tone(portlist, NULL);
3463 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3464 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3468 /* JOIN has pattern available */
3469 case MESSAGE_PATTERN: /* indicating pattern available */
3470 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);
3471 if (!e_join_pattern)
3473 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3478 set_tone(portlist, NULL);
3479 portlist = portlist->next;
3481 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3482 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3483 message->param.audiopath = CHANNEL_STATE_CONNECT;
3484 message_put(message);
3485 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3486 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_REMOTE_AUDIO);
3487 // message->param.audiopath = CHANNEL_STATE_CONNECT;
3488 // message_put(message);
3489 // patterns are available, remote already connected audio
3493 /* JOIN has no pattern available */
3494 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3495 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);
3498 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3500 /* disconnect our audio tx and rx */
3501 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3502 message->param.audiopath = CHANNEL_STATE_HOLD;
3503 message_put(message);
3508 /* JOIN (dunno at the moment) */
3509 case MESSAGE_REMOTE_AUDIO:
3510 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);
3511 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3512 message->param.audiopath = param->channel;
3513 message_put(message);
3517 /* JOIN sends a notify message */
3518 case MESSAGE_NOTIFY:
3519 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);
3520 join_notify(portlist, message_type, param);
3524 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);
3529 /* pick_join will connect the first incoming call found. the endpoint
3530 * will receivce a MESSAGE_CONNECT.
3532 int match_list(char *list, char *item)
3534 char *end, *next = NULL;
3536 /* no list make matching */
3542 /* eliminate white spaces */
3543 while (*list <= ' ')
3550 /* if end of list is reached, we return */
3551 if (list[0] == '\0')
3553 /* if we have more than one entry (left) */
3554 if ((end = strchr(list, ',')))
3557 next = end = strchr(list, '\0');
3558 while (*(end-1) <= ' ')
3560 /* if string part matches item */
3561 if (!strncmp(list, item, end-list))
3567 void EndpointAppPBX::pick_join(char *extensions)
3569 struct message *message;
3570 struct port_list *portlist;
3572 class EndpointAppPBX *eapp, *found;
3574 class JoinPBX *joinpbx;
3575 struct join_relation *relation;
3578 /* find an endpoint that is ringing internally or vbox with higher priority */
3581 eapp = apppbx_first;
3584 if (eapp!=this && ea_endpoint->ep_portlist)
3586 portlist = eapp->ea_endpoint->ep_portlist;
3589 if ((port = find_port_id(portlist->port_id)))
3591 if (port->p_type == PORT_TYPE_VBOX_OUT)
3593 if (match_list(extensions, eapp->e_ext.number))
3600 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3601 && port->p_state==PORT_STATE_OUT_ALERTING)
3602 if (match_list(extensions, eapp->e_ext.number))
3607 portlist = portlist->next;
3615 /* if no endpoint found */
3618 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);
3620 set_tone(ea_endpoint->ep_portlist, "cause_10");
3621 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3622 new_state(EPOINT_STATE_OUT_DISCONNECT);
3627 if (ea_endpoint->ep_join_id)
3629 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3632 if (!eapp->ea_endpoint->ep_join_id)
3634 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3637 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3640 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3643 if (join->j_type != JOIN_TYPE_PBX)
3645 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3648 joinpbx = (class JoinPBX *)join;
3649 relation = joinpbx->j_relation;
3652 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3655 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3657 relation = relation->next;
3660 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3665 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3667 if (options.deb & DEBUG_EPOINT)
3669 class Join *debug_c = join_first;
3670 class Endpoint *debug_e = epoint_first;
3671 class Port *debug_p = port_first;
3673 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3675 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3678 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3679 debug_c = debug_c->next;
3681 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3684 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3685 debug_e = debug_e->next;
3687 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3690 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3691 debug_p = debug_p->next;
3696 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3697 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3698 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3700 /* connnecting our endpoint */
3701 new_state(EPOINT_STATE_CONNECT);
3703 set_tone(ea_endpoint->ep_portlist, NULL);
3705 /* now we send a release to the ringing endpoint */
3706 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3707 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3708 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3709 message_put(message);
3711 /* we send a connect to the join with our caller id */
3712 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3713 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3714 message->param.connectinfo.present = e_callerinfo.present;
3715 message->param.connectinfo.screen = e_callerinfo.screen;
3716 message->param.connectinfo.itype = e_callerinfo.itype;
3717 message->param.connectinfo.ntype = e_callerinfo.ntype;
3718 message_put(message);
3720 /* we send a connect to our port with the remote callerid */
3721 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3722 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3723 message->param.connectinfo.present = eapp->e_callerinfo.present;
3724 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3725 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3726 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3727 /* handle restricted caller ids */
3728 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);
3729 /* display callerid if desired for extension */
3730 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));
3731 message_put(message);
3733 /* we send a connect to the audio path (not for vbox) */
3734 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3735 message->param.audiopath = CHANNEL_STATE_CONNECT;
3736 message_put(message);
3738 /* beeing paranoid, we make call update */
3739 joinpbx->j_updatebridge = 1;
3741 if (options.deb & DEBUG_EPOINT)
3743 class Join *debug_c = join_first;
3744 class Endpoint *debug_e = epoint_first;
3745 class Port *debug_p = port_first;
3747 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3749 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3752 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3753 debug_c = debug_c->next;
3755 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3758 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3759 debug_e = debug_e->next;
3761 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3764 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3765 debug_p = debug_p->next;
3771 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3773 void EndpointAppPBX::join_join(void)
3775 struct message *message;
3776 struct join_relation *our_relation, *other_relation;
3777 struct join_relation **our_relation_pointer, **other_relation_pointer;
3778 class Join *our_join, *other_join;
3779 class JoinPBX *our_joinpbx, *other_joinpbx;
3780 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3781 class Port *our_port, *other_port;
3782 class Pdss1 *our_pdss1, *other_pdss1;
3784 /* are we a candidate to join a join */
3785 our_join = find_join_id(ea_endpoint->ep_join_id);
3788 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3791 if (our_join->j_type != JOIN_TYPE_PBX)
3793 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3796 our_joinpbx = (class JoinPBX *)our_join;
3797 if (!ea_endpoint->ep_portlist)
3799 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3802 if (!e_ext.number[0])
3804 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3807 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3810 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3813 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3815 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3818 our_pdss1 = (class Pdss1 *)our_port;
3820 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3821 other_eapp = apppbx_first;
3824 if (other_eapp == this)
3826 other_eapp = other_eapp->next;
3829 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);
3830 if (other_eapp->e_ext.number[0] /* has terminal */
3831 && other_eapp->ea_endpoint->ep_portlist /* has port */
3832 && other_eapp->ea_endpoint->ep_join_id) /* has join */
3834 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3835 if (other_port) /* port still exists */
3837 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3838 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3840 other_pdss1 = (class Pdss1 *)other_port;
3841 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);
3842 if (other_pdss1->p_m_hold /* port is on hold */
3843 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3844 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3848 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3852 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3855 other_eapp = other_eapp->next;
3859 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3862 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3864 /* if we have the same join */
3865 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
3867 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
3870 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3873 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3876 if (other_join->j_type != JOIN_TYPE_PBX)
3878 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3881 other_joinpbx = (class JoinPBX *)other_join;
3882 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
3884 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3888 /* remove relation to endpoint for join on hold */
3889 other_relation = other_joinpbx->j_relation;
3890 other_relation_pointer = &other_joinpbx->j_relation;
3891 while(other_relation)
3893 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
3895 /* detach other endpoint on hold */
3896 *other_relation_pointer = other_relation->next;
3897 FREE(other_relation, sizeof(struct join_relation));
3899 other_relation = *other_relation_pointer;
3900 other_eapp->ea_endpoint->ep_join_id = NULL;
3904 /* change join/hold pointer of endpoint to the new join */
3905 temp_epoint = find_epoint_id(other_relation->epoint_id);
3908 if (temp_epoint->ep_join_id == other_join->j_serial)
3909 temp_epoint->ep_join_id = our_join->j_serial;
3912 other_relation_pointer = &other_relation->next;
3913 other_relation = other_relation->next;
3915 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3917 /* join call relations */
3918 our_relation = our_joinpbx->j_relation;
3919 our_relation_pointer = &our_joinpbx->j_relation;
3922 our_relation_pointer = &our_relation->next;
3923 our_relation = our_relation->next;
3925 *our_relation_pointer = other_joinpbx->j_relation;
3926 other_joinpbx->j_relation = NULL;
3927 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3929 /* release endpoint on hold */
3930 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3931 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3932 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3933 message_put(message);
3935 /* if we are not a partyline, we get partyline state from other join */
3936 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3938 /* remove empty join */
3940 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3942 /* mixer must update */
3943 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
3945 /* we send a retrieve to that endpoint */
3946 // mixer will update the hold-state of the join and send it to the endpoints is changes
3950 /* check if we have an external call
3951 * this is used to check for encryption ability
3953 int EndpointAppPBX::check_external(char **errstr, class Port **port)
3955 struct join_relation *relation;
3957 class JoinPBX *joinpbx;
3958 class Endpoint *epoint;
3960 /* some paranoia check */
3961 if (!ea_endpoint->ep_portlist)
3963 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3964 *errstr = "No Call";
3967 if (!e_ext.number[0])
3969 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
3970 *errstr = "No Call";
3974 /* check if we have a join with 2 parties */
3975 join = find_join_id(ea_endpoint->ep_join_id);
3978 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
3979 *errstr = "No Call";
3982 if (join->j_type != JOIN_TYPE_PBX)
3984 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
3985 *errstr = "No PBX Call";
3988 joinpbx = (class JoinPBX *)join;
3989 relation = joinpbx->j_relation;
3992 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
3993 *errstr = "No Call";
3996 if (!relation->next)
3998 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
3999 *errstr = "No Call";
4002 if (relation->next->next)
4004 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4005 *errstr = "Err: Conference";
4008 if (relation->epoint_id == ea_endpoint->ep_serial)
4010 relation = relation->next;
4011 if (relation->epoint_id == ea_endpoint->ep_serial)
4013 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4014 *errstr = "Software Error";
4019 /* check remote port for external call */
4020 epoint = find_epoint_id(relation->epoint_id);
4023 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4024 *errstr = "No Call";
4027 if (!epoint->ep_portlist)
4029 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4030 *errstr = "No Call";
4033 *port = find_port_id(epoint->ep_portlist->port_id);
4036 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4037 *errstr = "No Call";
4040 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4042 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4043 *errstr = "No Ext Call";
4046 if ((*port)->p_state != PORT_STATE_CONNECT)
4048 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4049 *errstr = "No Ext Connect";
4055 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned long port_id, int dir)
4057 char *logtext = "unknown";
4060 switch(message_type)
4063 trace_header("SETUP", dir);
4064 if (dir == DIRECTION_OUT)
4065 add_trace("to", NULL, "CH(%lu)", port_id);
4066 if (dir == DIRECTION_IN)
4067 add_trace("from", NULL, "CH(%lu)", port_id);
4068 if (param->setup.callerinfo.extension[0])
4069 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4070 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype));
4071 switch(param->setup.callerinfo.present)
4073 case INFO_PRESENT_RESTRICTED:
4074 add_trace("caller id", "present", "restricted");
4076 case INFO_PRESENT_ALLOWED:
4077 add_trace("caller id", "present", "allowed");
4080 add_trace("caller id", "present", "not available");
4082 if (param->setup.redirinfo.id[0])
4084 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype));
4085 switch(param->setup.redirinfo.present)
4087 case INFO_PRESENT_RESTRICTED:
4088 add_trace("redir'ing", "present", "restricted");
4090 case INFO_PRESENT_ALLOWED:
4091 add_trace("redir'ing", "present", "allowed");
4094 add_trace("redir'ing", "present", "not available");
4097 if (param->setup.dialinginfo.id[0])
4098 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4102 case MESSAGE_OVERLAP:
4103 trace_header("SETUP ACKNOWLEDGE", 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_PROCEEDING:
4112 trace_header("PROCEEDING", 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);
4120 case MESSAGE_ALERTING:
4121 trace_header("ALERTING", dir);
4122 if (dir == DIRECTION_OUT)
4123 add_trace("to", NULL, "CH(%lu)", port_id);
4124 if (dir == DIRECTION_IN)
4125 add_trace("from", NULL, "CH(%lu)", port_id);
4129 case MESSAGE_CONNECT:
4130 trace_header("CONNECT", dir);
4131 if (dir == DIRECTION_OUT)
4132 add_trace("to", NULL, "CH(%lu)", port_id);
4133 if (dir == DIRECTION_IN)
4134 add_trace("from", NULL, "CH(%lu)", port_id);
4135 if (param->connectinfo.extension[0])
4136 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4137 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype));
4138 switch(param->connectinfo.present)
4140 case INFO_PRESENT_RESTRICTED:
4141 add_trace("connect id", "present", "restricted");
4143 case INFO_PRESENT_ALLOWED:
4144 add_trace("connect id", "present", "allowed");
4147 add_trace("connect id", "present", "not available");
4152 case MESSAGE_DISCONNECT:
4153 case MESSAGE_RELEASE:
4154 if (message_type == MESSAGE_DISCONNECT)
4155 trace_header("DISCONNECT", dir);
4157 trace_header("RELEASE", dir);
4158 if (dir == DIRECTION_OUT)
4159 add_trace("to", NULL, "CH(%lu)", port_id);
4160 if (dir == DIRECTION_IN)
4161 add_trace("from", NULL, "CH(%lu)", port_id);
4162 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4163 switch(param->disconnectinfo.location)
4166 add_trace("cause", "location", "0-User");
4168 case LOCATION_PRIVATE_LOCAL:
4169 add_trace("cause", "location", "1-Local-PBX");
4171 case LOCATION_PUBLIC_LOCAL:
4172 add_trace("cause", "location", "2-Local-Exchange");
4174 case LOCATION_TRANSIT:
4175 add_trace("cause", "location", "3-Transit");
4177 case LOCATION_PUBLIC_REMOTE:
4178 add_trace("cause", "location", "4-Remote-Exchange");
4180 case LOCATION_PRIVATE_REMOTE:
4181 add_trace("cause", "location", "5-Remote-PBX");
4183 case LOCATION_INTERNATIONAL:
4184 add_trace("cause", "location", "7-International-Exchange");
4186 case LOCATION_BEYOND:
4187 add_trace("cause", "location", "10-Beyond-Interworking");
4190 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4195 case MESSAGE_NOTIFY:
4196 switch(param->notifyinfo.notify)
4202 logtext = "USER_SUSPENDED";
4205 logtext = "BEARER_SERVICE_CHANGED";
4208 logtext = "USER_RESUMED";
4211 logtext = "CONFERENCE_ESTABLISHED";
4214 logtext = "CONFERENCE_DISCONNECTED";
4217 logtext = "OTHER_PARTY_ADDED";
4220 logtext = "ISOLATED";
4223 logtext = "REATTACHED";
4226 logtext = "OTHER_PARTY_ISOLATED";
4229 logtext = "OTHER_PARTY_REATTACHED";
4232 logtext = "OTHER_PARTY_SPLIT";
4235 logtext = "OTHER_PARTY_DISCONNECTED";
4238 logtext = "CONFERENCE_FLOATING";
4241 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4244 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4247 logtext = "CALL_IS_A_WAITING_CALL";
4250 logtext = "DIVERSION_ACTIVATED";
4253 logtext = "RESERVED_CT_1";
4256 logtext = "RESERVED_CT_2";
4259 logtext = "REVERSE_CHARGING";
4262 logtext = "REMOTE_HOLD";
4265 logtext = "REMOTE_RETRIEVAL";
4268 logtext = "CALL_IS_DIVERTING";
4271 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4275 trace_header("NOTIFY", dir);
4276 if (dir == DIRECTION_OUT)
4277 add_trace("to", NULL, "CH(%lu)", port_id);
4278 if (dir == DIRECTION_IN)
4279 add_trace("from", NULL, "CH(%lu)", port_id);
4280 if (param->notifyinfo.notify)
4281 add_trace("indicator", NULL, "%s", logtext);
4282 if (param->notifyinfo.id[0])
4284 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype));
4285 switch(param->notifyinfo.present)
4287 case INFO_PRESENT_RESTRICTED:
4288 add_trace("redir'on", "present", "restricted");
4290 case INFO_PRESENT_ALLOWED:
4291 add_trace("redir'on", "present", "allowed");
4294 add_trace("redir'on", "present", "not available");
4297 if (param->notifyinfo.display[0])
4298 add_trace("display", NULL, "%s", param->notifyinfo.display);
4302 case MESSAGE_INFORMATION:
4303 trace_header("INFORMATION", dir);
4304 if (dir == DIRECTION_OUT)
4305 add_trace("to", NULL, "CH(%lu)", port_id);
4306 if (dir == DIRECTION_IN)
4307 add_trace("from", NULL, "CH(%lu)", port_id);
4308 add_trace("dialing", NULL, "%s", param->information.id);
4312 case MESSAGE_FACILITY:
4313 trace_header("FACILITY", dir);
4314 if (dir == DIRECTION_OUT)
4315 add_trace("to", NULL, "CH(%lu)", port_id);
4316 if (dir == DIRECTION_IN)
4317 add_trace("from", NULL, "CH(%lu)", port_id);
4322 trace_header("TONE", dir);
4323 if (dir == DIRECTION_OUT)
4324 add_trace("to", NULL, "CH(%lu)", port_id);
4325 if (dir == DIRECTION_IN)
4326 add_trace("from", NULL, "CH(%lu)", port_id);
4327 if (param->tone.name[0])
4329 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4330 add_trace("name", NULL, "%s", param->tone.name);
4332 add_trace("off", NULL, NULL);
4336 case MESSAGE_SUSPEND:
4337 case MESSAGE_RESUME:
4338 if (message_type == MESSAGE_SUSPEND)
4339 trace_header("SUSPEND", dir);
4341 trace_header("RESUME", dir);
4342 if (dir == DIRECTION_OUT)
4343 add_trace("to", NULL, "CH(%lu)", port_id);
4344 if (dir == DIRECTION_IN)
4345 add_trace("from", NULL, "CH(%lu)", port_id);
4346 if (param->parkinfo.len)
4347 add_trace("length", NULL, "%d", param->parkinfo.len);
4352 case MESSAGE_BCHANNEL:
4353 trace_header("BCHANNEL", dir);
4354 switch(param->bchannel.type)
4356 case BCHANNEL_REQUEST:
4357 add_trace("type", NULL, "request");
4359 case BCHANNEL_ASSIGN:
4360 add_trace("type", NULL, "assign");
4362 case BCHANNEL_ASSIGN_ACK:
4363 add_trace("type", NULL, "assign_ack");
4365 case BCHANNEL_REMOVE:
4366 add_trace("type", NULL, "remove");
4368 case BCHANNEL_REMOVE_ACK:
4369 add_trace("type", NULL, "remove_ack");
4372 if (param->bchannel.addr)
4373 add_trace("address", NULL, "%x", param->bchannel.addr);
4379 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4383 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4385 struct message *message;
4389 if (!portlist->port_id)
4392 if (!e_connectedmode)
4394 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4395 message->param.disconnectinfo.cause = cause;
4396 message->param.disconnectinfo.location = location;
4398 SCPY(message->param.disconnectinfo.display, display);
4400 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4403 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4405 SCPY(message->param.notifyinfo.display, display);
4407 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4409 message_put(message);
4410 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);