1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 #include <sys/types.h>
23 class EndpointAppPBX *apppbx_first = NULL;
26 * EndpointAppPBX constructor
28 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint) : EndpointApp(epoint)
30 class EndpointAppPBX **apppointer;
32 /* add application to chain */
34 apppointer = &apppbx_first;
36 apppointer = &((*apppointer)->next);
40 memset(&e_ext, 0, sizeof(struct extension));
41 e_ext.rights = 4; /* international */
42 e_ext.rxvol = e_ext.txvol = 256;
43 e_state = EPOINT_STATE_IDLE;
44 e_ext.number[0] = '\0';
45 e_extension_interface[0] = '\0';
46 memset(&e_callerinfo, 0, sizeof(struct caller_info));
47 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
48 memset(&e_connectinfo, 0, sizeof(struct connect_info));
49 memset(&e_redirinfo, 0, sizeof(struct redir_info));
50 memset(&e_capainfo, 0, sizeof(struct capa_info));
53 e_ruleset = ruleset_main;
55 e_rule = e_ruleset->rule_first;
60 e_match_to_action = NULL;
62 e_extdialing = e_dialinginfo.id;
66 // e_join_tone[0] = e_hold_tone[0] = '\0';
67 e_join_pattern /*= e_hold_pattern*/ = 0;
70 e_adminid = 0; // will be set, if call was initiated via admin socket
75 e_cbdialing[0] = '\0';
78 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
85 e_password_timeout = 0;
86 e_multipoint_cause = 0;
87 e_multipoint_location = 0;
88 e_dialing_queue[0] = '\0';
90 e_crypt_state = CM_ST_NULL;
91 e_crypt_keyengine_busy = 0;
92 e_crypt_info[0] = '\0';
95 e_tx_state = NOTIFY_STATE_ACTIVE;
96 e_rx_state = NOTIFY_STATE_ACTIVE;
97 e_join_cause = e_join_location = 0;
98 /*********************************
99 *********************************
100 ********* ATTENTION *************
101 *********************************
102 *********************************/
103 /* if you add new values, that must be initialized, also check if they must
104 * be initialized when doing callback
110 * EpointAppPBX destructor
112 EndpointAppPBX::~EndpointAppPBX(void)
114 class EndpointAppPBX *temp, **tempp;
118 tempp = &apppbx_first;
128 FATAL("Endpoint not in endpoint's list.\n");
135 * trace header for application
137 void EndpointAppPBX::trace_header(char *name, int direction)
141 char msgtext[sizeof(_trace.name)];
145 /* init trace with given values */
148 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype),
152 ea_endpoint->ep_serial,
159 /* set new endpoint state
161 void EndpointAppPBX::new_state(int state)
164 if (e_state != state)
166 trace_header("NEW STATE", DIRECTION_NONE);
167 add_trace("state", "old", "%s", state_name[e_state]);
168 add_trace("state", "new", "%s", state_name[state]);
177 * out==0: incomming caller id, out==1: outgoing caller id
179 void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
182 struct interface_msn *ifmsn;
183 struct interface_screen *ifscreen;
186 /* screen incoming caller id */
189 /* check for MSN numbers, use first MSN if no match */
191 ifmsn = interface->ifmsn;
196 if (!strcmp(ifmsn->msn, id))
204 trace_header("SCREEN (found in MSN list)", DIRECTION_IN);
205 add_trace("msn", NULL, "%s", id);
208 if (!ifmsn && msn1) // not in list, first msn given
210 trace_header("SCREEN (not found MSN in list)", DIRECTION_IN);
211 add_trace("msn", "given", "%s", id);
212 add_trace("msn", "used", "%s", msn1);
214 UNCPY(id, msn1, idsize);
219 /* check screen list */
221 ifscreen = interface->ifscreen_out;
223 ifscreen = interface->ifscreen_in;
226 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
227 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
229 if (strchr(ifscreen->match,'%'))
231 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
235 if (!strcmp(ifscreen->match, id))
239 ifscreen = ifscreen->next;
241 if (ifscreen) // match
243 trace_header("SCREEN (found in screen list)", out?DIRECTION_OUT:DIRECTION_IN);
246 case INFO_NTYPE_UNKNOWN:
247 add_trace("given", "type", "unknown");
249 case INFO_NTYPE_SUBSCRIBER:
250 add_trace("given", "type", "subscriber");
252 case INFO_NTYPE_NATIONAL:
253 add_trace("given", "type", "national");
255 case INFO_NTYPE_INTERNATIONAL:
256 add_trace("given", "type", "international");
261 case INFO_PRESENT_ALLOWED:
262 add_trace("given", "present", "allowed");
264 case INFO_PRESENT_RESTRICTED:
265 add_trace("given", "present", "restricted");
267 case INFO_PRESENT_NOTAVAIL:
268 add_trace("given", "present", "not available");
271 add_trace("given", "id", "%s", id[0]?id:"<empty>");
272 if (ifscreen->result_type != -1)
274 *type = ifscreen->result_type;
277 case INFO_NTYPE_UNKNOWN:
278 add_trace("used", "type", "unknown");
280 case INFO_NTYPE_SUBSCRIBER:
281 add_trace("used", "type", "subscriber");
283 case INFO_NTYPE_NATIONAL:
284 add_trace("used", "type", "national");
286 case INFO_NTYPE_INTERNATIONAL:
287 add_trace("used", "type", "international");
291 if (ifscreen->result_present != -1)
293 *present = ifscreen->result_present;
296 case INFO_PRESENT_ALLOWED:
297 add_trace("used", "present", "allowed");
299 case INFO_PRESENT_RESTRICTED:
300 add_trace("used", "present", "restricted");
302 case INFO_PRESENT_NOTAVAIL:
303 add_trace("used", "present", "not available");
307 if (strchr(ifscreen->match,'%'))
309 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
310 UNCPY(id, ifscreen->result, idsize);
312 if (strchr(ifscreen->result,'%'))
314 *strchr(ifscreen->result,'%') = '\0';
315 UNCAT(id, suffix, idsize);
320 UNCPY(id, ifscreen->result, idsize);
323 add_trace("used", "id", "%s", id[0]?id:"<empty>");
328 /* release join and port (as specified)
330 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
332 struct port_list *portlist;
333 struct message *message;
336 /* message to test call */
337 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
339 /* if a release is pending */
340 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
342 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
343 if (ea_endpoint->ep_join_id)
345 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
346 message->param.disconnectinfo.cause = joincause;
347 message->param.disconnectinfo.location = joinlocation;
348 message_put(message);
349 ea_endpoint->ep_join_id = 0;
353 if (release != RELEASE_PORT_JOINONLY)
356 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
361 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
363 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
364 while((portlist = ea_endpoint->ep_portlist))
366 if (portlist->port_id)
368 SPRINT(cause, "cause_%02x", portcause);
369 set_tone(portlist, cause);
370 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
371 message->param.disconnectinfo.cause = portcause;
372 message->param.disconnectinfo.location = portlocation;
373 message_put(message);
374 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
376 ea_endpoint->free_portlist(portlist);
379 /* if callback is enabled, call back with the given caller id */
382 /* reset some stuff */
383 new_state(EPOINT_STATE_IDLE);
384 memset(&e_connectinfo, 0, sizeof(struct connect_info));
385 memset(&e_redirinfo, 0, sizeof(struct redir_info));
386 e_start = e_stop = 0;
387 e_ruleset = ruleset_main;
389 e_rule = e_ruleset->rule_first;
391 e_action_timeout = 0;
393 e_match_to_action = NULL;
395 e_extdialing = e_dialinginfo.id;
402 e_multipoint_cause = 0;
403 e_multipoint_location = 0;
404 e_dialing_queue[0] = '\0';
406 e_crypt_state = CM_ST_NULL;
407 e_crypt_keyengine_busy = 0;
408 e_crypt_info[0] = '\0';
412 e_tx_state = NOTIFY_STATE_ACTIVE;
413 e_rx_state = NOTIFY_STATE_ACTIVE;
414 e_join_cause = e_join_location = 0;
416 /* the caller info of the callback user */
417 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
418 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
419 /* create dialing by callerinfo */
420 if (e_ext.number[0] && e_extension_interface[0])
422 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
423 /* create callback to the current terminal */
424 SCPY(e_dialinginfo.id, e_ext.number);
425 SCPY(e_dialinginfo.interfaces, e_extension_interface);
426 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
427 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
432 SCPY(e_dialinginfo.id, e_cbto);
435 /* numberrize caller id and use it to dial to the callback */
436 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
438 e_dialinginfo.itype = INFO_ITYPE_ISDN;
439 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
440 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
445 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
446 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
452 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
453 void apply_callerid_restriction(int anon_ignore, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
455 PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d extension='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (extension)?extension:"NULL", (name)?name:"NULL");
457 /* caller id is not restricted, so we do nothing */
458 if (*present != INFO_PRESENT_RESTRICTED)
461 /* only extensions are restricted */
467 /* if we enabled anonymouse ignore */
471 /* else we remove the caller id */
475 *ntype = INFO_NTYPE_UNKNOWN;
477 // *screen = INFO_SCREEN_USER;
478 // maybe we should not make voip address anonymous
481 // maybe it's no fraud to present extension id
483 // extension[0] = '\0';
488 /* used display message to display callerid as available */
489 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *extension, char *name)
491 static char display[81];
494 char *cid = numberrize_callerinfo(id, ntype);
496 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d extension='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (extension)?extension:"NULL", (name)?name:"NULL");
505 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
507 /* internal extension's caller id */
508 if (extension[0] && e_ext.display_int)
511 SCAT(display, extension);
514 if (itype == INFO_ITYPE_VBOX)
515 SCAT(display, "(vbox)");
517 SCAT(display, "(int)");
520 /* external caller id */
521 if (!extension[0] && e_ext.display_ext)
527 if (present == INFO_PRESENT_RESTRICTED)
528 SCAT(display, "anonymous");
530 SCAT(display, "unknown");
537 /* display if callerid is anonymouse but available due anon-ignore */
538 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
541 SCAT(display, "unknown");
544 SCAT(display, " anon");
547 /* display if callerid is anonymouse but available due anon-ignore */
548 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
554 if (present == INFO_PRESENT_RESTRICTED)
555 SCAT(display, "anonymous");
557 SCAT(display, "unknown");
562 SCAT(display, " fake");
566 if (name[0] && e_ext.display_name)
568 if (!display[0] && cid[0])
579 * uses the current state to notify activity
581 void EndpointAppPBX::notify_active(void)
583 struct port_list *portlist = ea_endpoint->ep_portlist;
584 struct message *message;
589 case NOTIFY_STATE_ACTIVE:
590 /* we are already active, so we don't do anything */
593 case NOTIFY_STATE_SUSPEND:
594 notify = INFO_NOTIFY_USER_RESUMED;
597 set_tone(portlist, NULL);
598 portlist = portlist->next;
600 portlist = ea_endpoint->ep_portlist;
603 case NOTIFY_STATE_HOLD:
604 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
607 set_tone(portlist, NULL);
608 portlist = portlist->next;
610 portlist = ea_endpoint->ep_portlist;
613 case NOTIFY_STATE_CONFERENCE:
614 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
617 set_tone(portlist, NULL);
618 portlist = portlist->next;
620 portlist = ea_endpoint->ep_portlist;
624 PERROR("unknown e_tx_state = %d\n", e_tx_state);
630 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
631 message->param.notifyinfo.notify = notify;
632 message_put(message);
633 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
634 portlist = portlist->next;
640 * keypad functions during call. one example to use this is to put a call on hold or start a conference
642 void EndpointAppPBX::keypad_function(char digit)
645 /* we must be in a call, in order to send messages to the call */
646 if (e_ext.number[0] == '\0')
648 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
654 /* join conference */
656 if (ea_endpoint->ep_join_id == 0)
658 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
661 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
667 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
671 /* crypt key-exchange */
673 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
679 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
684 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
689 /* set tone pattern for port */
690 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
692 struct message *message;
697 /* store for suspended processes */
701 if (e_join_pattern /* pattern are provided */
702 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
703 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
704 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
705 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
706 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
707 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
708 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
709 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
710 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
711 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
712 && tone[0] && !!strncmp(tone,"crypt_*",6))
714 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
720 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
721 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
722 SCPY(message->param.tone.name, tone);
723 message_put(message);
724 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
727 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
734 * hunts an mISDNport that is available for an outgoing call
735 * if no ifname was given, any interface that is not an extension
738 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
740 struct interface *interface;
741 struct interface_port *ifport, *ifport_start;
742 struct select_channel *selchannel;
743 struct mISDNport *mISDNport;
746 interface = interface_first;
748 /* first find the given interface or, if not given, one with no extension */
753 /* check for given interface */
756 if (!strcasecmp(interface->name, ifname))
758 /* found explicit interface */
759 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
760 add_trace("interface", NULL, "%s", ifname);
767 if (!interface->extension)
769 /* found non extension */
770 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
771 add_trace("interface", NULL, "%s", interface->name);
777 interface = interface->next;
781 /* see if interface has ports */
782 if (!interface->ifport)
785 trace_header("CHANNEL SELECTION (interface has no active ports, skipping)", DIRECTION_NONE);
786 add_trace("interface", NULL, "%s", interface->name);
788 interface = interface->next;
792 /* select port by algorithm */
793 ifport_start = interface->ifport;
795 if (interface->hunt == HUNT_ROUNDROBIN)
797 while(ifport_start->next && index<interface->hunt_next)
799 ifport_start = ifport_start->next;
802 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
803 add_trace("port", NULL, "%d", ifport_start->portnum);
804 add_trace("position", NULL, "%d", index);
809 ifport = ifport_start;
812 /* see if port is available */
813 if (!ifport->mISDNport)
815 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
816 add_trace("port", NULL, "%d", ifport->portnum);
817 add_trace("position", NULL, "%d", index);
821 mISDNport = ifport->mISDNport;
823 /* see if port is administratively blocked */
826 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
827 add_trace("port", NULL, "%d", ifport->portnum);
828 add_trace("position", NULL, "%d", index);
833 /* see if link is up on PTP*/
834 if (mISDNport->ptp && !mISDNport->l2link)
836 trace_header("CHANNEL SELECTION (port is ptp with layer 2 down, skipping)", DIRECTION_NONE);
837 add_trace("port", NULL, "%d", ifport->portnum);
838 add_trace("position", NULL, "%d", index);
843 /* check for channel form selection list */
845 selchannel = ifport->out_channel;
848 switch(selchannel->channel)
850 case CHANNEL_FREE: /* free channel */
851 if (mISDNport->b_reserved >= mISDNport->b_num)
852 break; /* all channel in use or reserverd */
855 while(i < mISDNport->b_num)
857 if (mISDNport->b_port[i] == NULL)
859 *channel = i+1+(i>=15);
860 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
861 add_trace("port", NULL, "%d", ifport->portnum);
862 add_trace("position", NULL, "%d", index);
863 add_trace("channel", NULL, "%d", *channel);
869 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
870 add_trace("port", NULL, "%d", ifport->portnum);
871 add_trace("position", NULL, "%d", index);
875 case CHANNEL_ANY: /* don't ask for channel */
876 if (mISDNport->b_reserved >= mISDNport->b_num)
878 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
879 add_trace("port", NULL, "%d", ifport->portnum);
880 add_trace("position", NULL, "%d", index);
881 add_trace("total", NULL, "%d", mISDNport->b_num);
882 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
884 break; /* all channel in use or reserverd */
886 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
887 add_trace("port", NULL, "%d", ifport->portnum);
888 add_trace("position", NULL, "%d", index);
890 *channel = CHANNEL_ANY;
893 case CHANNEL_NO: /* call waiting */
894 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
895 add_trace("port", NULL, "%d", ifport->portnum);
896 add_trace("position", NULL, "%d", index);
898 *channel = CHANNEL_NO;
902 if (selchannel->channel<1 || selchannel->channel==16)
904 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
905 add_trace("port", NULL, "%d", ifport->portnum);
906 add_trace("position", NULL, "%d", index);
907 add_trace("channel", NULL, "%d", selchannel->channel);
909 break; /* invalid channels */
911 i = selchannel->channel-1-(selchannel->channel>=17);
912 if (i >= mISDNport->b_num)
914 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
915 add_trace("port", NULL, "%d", ifport->portnum);
916 add_trace("position", NULL, "%d", index);
917 add_trace("channel", NULL, "%d", selchannel->channel);
918 add_trace("channels", NULL, "%d", mISDNport->b_num);
920 break; /* channel not in port */
922 if (mISDNport->b_port[i] == NULL)
924 *channel = selchannel->channel;
925 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
926 add_trace("port", NULL, "%d", ifport->portnum);
927 add_trace("position", NULL, "%d", index);
928 add_trace("channel", NULL, "%d", *channel);
935 break; /* found channel */
936 selchannel = selchannel->next;
939 /* if channel was found, return mISDNport and channel */
942 /* setting next port to start next time */
943 if (interface->hunt == HUNT_ROUNDROBIN)
948 interface->hunt_next = index;
954 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
955 add_trace("port", NULL, "%d", ifport->portnum);
956 add_trace("position", NULL, "%d", index);
960 /* go next port, until all ports are checked */
962 ifport = ifport->next;
966 ifport = interface->ifport;
968 if (ifport != ifport_start)
971 return(NULL); /* no port found */
974 /* outgoing setup to port(s)
975 * ports will be created and a setup is sent if everything is ok. otherwhise
976 * the endpoint is destroyed.
978 void EndpointAppPBX::out_setup(void)
980 struct dialing_info dialinginfo;
982 // class pdss1 *pdss1;
983 struct port_list *portlist;
984 struct message *message;
986 int cause = CAUSE_RESSOURCEUNAVAIL;
989 struct mISDNport *mISDNport;
992 class EndpointAppPBX *atemp;
993 // char allowed_ports[256];
995 char ifname[sizeof(e_ext.interfaces)],
997 struct port_settings port_settings;
1001 /* create settings for creating port */
1002 memset(&port_settings, 0, sizeof(port_settings));
1003 if (e_ext.tones_dir)
1004 SCPY(port_settings.tones_dir, e_ext.tones_dir);
1006 SCPY(port_settings.tones_dir, options.tones_dir);
1007 port_settings.tout_setup = e_ext.tout_setup;
1008 port_settings.tout_dialing = e_ext.tout_dialing;
1009 port_settings.tout_proceeding = e_ext.tout_proceeding;
1010 port_settings.tout_alerting = e_ext.tout_alerting;
1011 port_settings.tout_disconnect = e_ext.tout_disconnect;
1012 // port_settings.tout_hold = e_ext.tout_hold;
1013 // port_settings.tout_park = e_ext.tout_park;
1014 port_settings.no_seconds = e_ext.no_seconds;
1016 /* 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 */
1018 /* check what dialinginfo.itype we got */
1019 switch(e_dialinginfo.itype)
1021 /* *********************** call to extension or vbox */
1022 case INFO_ITYPE_ISDN_EXTENSION:
1023 /* check if we deny incoming calls when we use an extension */
1024 if (e_ext.noknocking)
1026 atemp = apppbx_first;
1030 if (!strcmp(atemp->e_ext.number, e_ext.number))
1032 atemp = atemp->next;
1036 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
1037 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
1038 return; /* must exit here */
1041 /* FALL THROUGH !!!! */
1042 case INFO_ITYPE_VBOX:
1043 /* get dialed extension's info */
1044 // SCPY(exten, e_dialinginfo.id);
1045 // if (strchr(exten, ','))
1046 // *strchr(exten, ',') = '\0';
1047 // if (!read_extension(&e_ext, exten))
1048 if (!read_extension(&e_ext, e_dialinginfo.id))
1050 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1051 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1052 return; /* must exit here */
1055 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
1057 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
1062 /* string from unconditional call forward (cfu) */
1066 /* present to forwarded party */
1067 if (e_ext.anon_ignore && e_callerinfo.id[0])
1069 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1071 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1075 /* string from busy call forward (cfb) */
1079 class EndpointAppPBX *checkapp = apppbx_first;
1082 if (checkapp != this) /* any other endpoint except our own */
1084 if (!strcmp(checkapp->e_ext.number, e_ext.number))
1086 /* present to forwarded party */
1087 if (e_ext.anon_ignore && e_callerinfo.id[0])
1089 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1091 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1095 checkapp = checkapp->next;
1099 /* string from no-response call forward (cfnr) */
1103 /* when cfnr is done, out_setup() will setup the call */
1106 /* present to forwarded party */
1107 if (e_ext.anon_ignore && e_callerinfo.id[0])
1109 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1113 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1115 e_cfnr_release = now + e_ext.cfnr_delay;
1116 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
1117 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);
1121 /* call to all internal interfaces */
1122 p = e_ext.interfaces;
1123 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1127 while(*p!=',' && *p!='\0')
1129 SCCAT(ifname, *p++);
1132 /* found interface */
1133 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
1134 /* hunt for mISDNport and create Port */
1135 mISDNport = hunt_port(ifname, &channel);
1138 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
1139 add_trace("interface", NULL, "%s", ifname);
1143 /* creating INTERNAL port */
1144 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1145 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force);
1147 FATAL("No memory for DSS1 Port instance\n");
1148 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1149 memset(&dialinginfo, 0, sizeof(dialinginfo));
1150 SCPY(dialinginfo.id, e_dialinginfo.id);
1151 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1152 dialinginfo.ntype = e_dialinginfo.ntype;
1153 /* create port_list relation */
1154 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1157 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1159 goto check_anycall_intern;
1161 /* directory.list */
1162 if (e_callerinfo.id[0] && (e_ext.centrex || e_ext.display_name))
1164 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1166 SCPY(e_callerinfo.name, dirname);
1168 // dss1 = (class Pdss1 *)port;
1170 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1171 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1172 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1173 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1174 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1175 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1176 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1177 //terminal if (e_dialinginfo.id)
1178 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1179 /* handle restricted caller ids */
1180 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1181 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1182 /* display callerid if desired for extension */
1183 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));
1184 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1185 /* use cnip, if enabld */
1187 message->param.setup.callerinfo.name[0] = '\0';
1188 /* screen clip if prefix is required */
1189 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1191 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1192 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
1193 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1195 /* use internal caller id */
1196 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1198 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1199 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1201 message_put(message);
1202 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1206 /* string from parallel call forward (cfp) */
1210 if (e_ext.anon_ignore && e_callerinfo.id[0])
1212 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1216 vbox_only: /* entry point for answering machine only */
1217 cfu_only: /* entry point for cfu */
1218 cfb_only: /* entry point for cfb */
1219 cfnr_only: /* entry point for cfnr */
1220 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1225 /* only if vbox should be dialed, and terminal is given */
1226 if (!strcmp(p, "vbox") && e_ext.number[0])
1228 /* go to the end of p */
1231 /* answering vbox call */
1232 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1234 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1235 FATAL("No memory for VBOX Port instance\n");
1236 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1237 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1241 while(*p!=',' && *p!='\0')
1246 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1247 /* hunt for mISDNport and create Port */
1248 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1251 /* creating EXTERNAL port*/
1252 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1253 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)))
1254 FATAL("No memory for DSS1 Port instance\n");
1255 earlyb = mISDNport->earlyb;
1259 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1260 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1266 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1267 goto check_anycall_intern;
1269 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1270 memset(&dialinginfo, 0, sizeof(dialinginfo));
1271 SCPY(dialinginfo.id, cfp);
1272 dialinginfo.itype = INFO_ITYPE_ISDN;
1273 dialinginfo.ntype = e_dialinginfo.ntype;
1274 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1277 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1279 goto check_anycall_intern;
1281 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1282 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1283 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1284 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1285 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1286 /* if clip is hidden */
1287 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1289 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1290 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1291 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1292 message->param.setup.callerinfo.present = e_ext.callerid_present;
1294 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1295 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1296 //terminal if (e_dialinginfo.id)
1297 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1298 /* handle restricted caller ids */
1299 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1300 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1301 /* display callerid if desired for extension */
1302 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));
1303 message_put(message);
1304 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1308 check_anycall_intern:
1309 /* now we have all ports created */
1312 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1314 if (!ea_endpoint->ep_join_id)
1316 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1317 return; /* must exit here */
1321 /* *********************** external call */
1323 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1324 /* call to extenal interfaces */
1325 p = e_dialinginfo.id;
1329 while(*p!=',' && *p!='\0')
1330 SCCAT(number, *p++);
1334 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");
1335 /* hunt for mISDNport and create Port */
1336 /* hunt for mISDNport and create Port */
1337 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1340 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1341 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1343 goto check_anycall_extern;
1345 /* creating EXTERNAL port*/
1346 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1347 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)))
1348 FATAL("No memory for DSS1 Port instance\n");
1349 earlyb = mISDNport->earlyb;
1350 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1351 memset(&dialinginfo, 0, sizeof(dialinginfo));
1352 SCPY(dialinginfo.id, number);
1353 dialinginfo.itype = INFO_ITYPE_ISDN;
1354 dialinginfo.ntype = e_dialinginfo.ntype;
1355 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1358 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1360 goto check_anycall_extern;
1362 // dss1 = (class Pdss1 *)port;
1363 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1364 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1365 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1366 SCPY(message->param.setup.dialinginfo.id, number);
1367 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1368 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1369 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1370 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1371 //terminal if (e_dialinginfo.id)
1372 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1373 /* handle restricted caller ids */
1374 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1375 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1376 /* display callerid if desired for extension */
1377 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));
1378 message_put(message);
1379 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1383 check_anycall_extern:
1384 /* now we have all ports created */
1387 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1389 if (!ea_endpoint->ep_join_id)
1391 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1392 return; /* must exit here */
1400 /* handler for endpoint
1404 int EndpointAppPBX::handler(void)
1406 if (e_crypt_state!=CM_ST_NULL)
1411 /* process answering machine (play) handling */
1414 if (e_action->index == ACTION_VBOX_PLAY)
1417 /* process action timeout */
1418 if (e_action_timeout)
1419 if (now_d >= e_action_timeout)
1421 if (e_state!=EPOINT_STATE_CONNECT)
1424 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1425 e_multipoint_cause = 0;
1426 e_multipoint_location = 0;
1427 new_state(EPOINT_STATE_IN_OVERLAP);
1430 return(1); /* we must exit, because our endpoint might be gone */
1432 e_action_timeout = 0;
1435 /* process action timeout */
1436 if (e_match_timeout)
1437 if (now_d >= e_match_timeout)
1440 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1442 return(1); /* we must exit, because our endpoint might be gone */
1447 /* process redialing (epoint redials to port) */
1450 if (now_d >= e_redial)
1453 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1455 new_state(EPOINT_STATE_OUT_SETUP);
1456 /* call special setup routine */
1463 /* process powerdialing (epoint redials to epoint) */
1464 if (e_powerdialing > 0)
1466 if (now_d >= e_powerdialing)
1468 e_powerdialing = -1; /* leave power dialing on */
1469 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1472 e_ruleset = ruleset_main;
1474 e_rule = e_ruleset->rule_first;
1476 new_state(EPOINT_STATE_IN_OVERLAP);
1482 /* process call forward no response */
1485 struct port_list *portlist;
1486 struct message *message;
1488 if (now >= e_cfnr_release)
1490 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1493 /* release all ports */
1494 while((portlist = ea_endpoint->ep_portlist))
1496 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1497 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1498 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1499 message_put(message);
1500 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1501 ea_endpoint->free_portlist(portlist);
1504 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1505 message->param.audiopath = CHANNEL_STATE_HOLD;
1506 message_put(message);
1507 /* indicate no patterns */
1508 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1509 message_put(message);
1510 /* set setup state, since we have no response from the new join */
1511 new_state(EPOINT_STATE_OUT_SETUP);
1516 if (now >= e_cfnr_call)
1518 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1524 /* handle connection to user */
1525 if (e_state == EPOINT_STATE_IDLE)
1527 /* epoint is idle, check callback */
1529 if (now_d >= e_callback)
1531 e_callback = 0; /* done with callback */
1532 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1533 new_state(EPOINT_STATE_OUT_SETUP);
1539 /* check for password timeout */
1541 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1543 struct port_list *portlist;
1545 if (now >= e_password_timeout)
1547 e_ruleset = ruleset_main;
1549 e_rule = e_ruleset->rule_first;
1551 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1552 trace_header("PASSWORD timeout", DIRECTION_NONE);
1554 e_connectedmode = 0;
1556 new_state(EPOINT_STATE_OUT_DISCONNECT);
1557 portlist = ea_endpoint->ep_portlist;
1560 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1561 set_tone(portlist, "cause_10");
1571 /* doing a hookflash */
1572 void EndpointAppPBX::hookflash(void)
1576 /* be sure that we are active */
1578 e_tx_state = NOTIFY_STATE_ACTIVE;
1580 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1582 if (ea_endpoint->ep_use > 1)
1584 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1587 /* dialtone after pressing the hash key */
1588 process_hangup(e_join_cause, e_join_location);
1589 e_multipoint_cause = 0;
1590 e_multipoint_location = 0;
1591 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1594 port->set_echotest(0);
1596 if (ea_endpoint->ep_join_id)
1598 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1600 e_ruleset = ruleset_main;
1602 e_rule = e_ruleset->rule_first;
1604 new_state(EPOINT_STATE_IN_OVERLAP);
1605 e_connectedmode = 1;
1606 SCPY(e_dialinginfo.id, e_ext.prefix);
1607 e_extdialing = e_dialinginfo.id;
1609 if (e_dialinginfo.id[0])
1611 set_tone(ea_endpoint->ep_portlist, "dialing");
1615 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1622 /* messages from port
1624 /* port MESSAGE_SETUP */
1625 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1627 struct message *message;
1629 int writeext; /* flags need to write extension after modification */
1631 struct interface *interface;
1633 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1635 portlist->port_type = param->setup.port_type;
1636 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1637 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1638 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1639 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1640 e_dtmf = param->setup.dtmf;
1641 /* screen incoming caller id */
1642 interface = interface_first;
1645 if (!strcmp(e_callerinfo.interface, interface->name))
1649 interface = interface->next;
1652 screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1654 /* process extension */
1655 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1657 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1658 /* port makes call from extension */
1659 SCPY(e_callerinfo.extension, e_callerinfo.id);
1660 SCPY(e_ext.number, e_callerinfo.extension);
1661 SCPY(e_extension_interface, e_callerinfo.interface);
1664 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1667 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1669 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1671 /* get extension's info about caller */
1672 if (!read_extension(&e_ext, e_ext.number))
1674 /* extension doesn't exist */
1675 trace_header("EXTENSION (not created)", DIRECTION_IN);
1676 add_trace("extension", NULL, "%s", e_ext.number);
1678 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1679 new_state(EPOINT_STATE_OUT_DISCONNECT);
1680 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1681 e_ext.number[0] = '\0'; /* no terminal */
1686 /* put prefix (next) in front of e_dialinginfo.id */
1689 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1690 SCPY(e_dialinginfo.id, buffer);
1691 e_ext.next[0] = '\0';
1693 } else if (e_ext.prefix[0])
1695 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1696 SCPY(e_dialinginfo.id, buffer);
1699 /* screen caller id by extension's config */
1700 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1702 SCPY(e_callerinfo.name, e_ext.name);
1703 /* use caller id (or if exist: id_next_call) for this call */
1704 if (e_ext.id_next_call_present >= 0)
1706 SCPY(e_callerinfo.id, e_ext.id_next_call);
1707 /* if we restrict the pesentation */
1708 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1709 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1710 else e_callerinfo.present = e_ext.id_next_call_present;
1711 e_callerinfo.ntype = e_ext.id_next_call_type;
1712 e_ext.id_next_call_present = -1;
1716 SCPY(e_callerinfo.id, e_ext.callerid);
1717 /* if we restrict the pesentation */
1718 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1719 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1720 else e_callerinfo.present = e_ext.callerid_present;
1721 e_callerinfo.ntype = e_ext.callerid_type;
1724 /* extension is written */
1726 write_extension(&e_ext, e_ext.number);
1728 /* set volume of rx and tx */
1729 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1730 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
1732 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1733 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1734 message->param.mISDNsignal.rxvol = e_ext.txvol;
1735 message->param.mISDNsignal.txvol = e_ext.rxvol;
1736 message_put(message);
1739 /* start recording if enabled */
1740 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1742 /* check if we are a terminal */
1743 if (e_ext.number[0] == '\0')
1744 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1747 port = find_port_id(portlist->port_id);
1749 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1754 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1755 /* no terminal identification */
1756 e_ext.number[0] = '\0';
1757 e_extension_interface[0] = '\0';
1758 memset(&e_ext, 0, sizeof(e_ext));
1759 e_ext.rights = 4; /* right to dial internat */
1763 e_ruleset = ruleset_main;
1765 e_rule = e_ruleset->rule_first;
1767 e_extdialing = e_dialinginfo.id;
1768 new_state(EPOINT_STATE_IN_SETUP);
1769 if (e_dialinginfo.id[0])
1771 set_tone(portlist, "dialing");
1774 if (e_ext.number[0])
1775 set_tone(portlist, "dialpbx");
1777 set_tone(portlist, "dialtone");
1780 if (e_state == EPOINT_STATE_IN_SETUP)
1782 /* request MORE info, if not already at higher state */
1783 new_state(EPOINT_STATE_IN_OVERLAP);
1784 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1785 message_put(message);
1786 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1790 /* port MESSAGE_INFORMATION */
1791 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1793 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1797 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1800 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1805 /* if vbox_play is done, the information are just used as they come */
1807 if (e_action->index == ACTION_VBOX_PLAY)
1809 /* concat dialing string */
1810 SCAT(e_dialinginfo.id, param->information.id);
1815 /* keypad when disconnect but in connected mode */
1816 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1818 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1819 /* processing keypad function */
1820 if (param->information.id[0] == '0')
1827 /* keypad when connected */
1828 if (e_state == EPOINT_STATE_CONNECT)
1832 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1833 /* processing keypad function */
1834 if (param->information.id[0] == '0')
1838 if (param->information.id[0])
1839 keypad_function(param->information.id[0]);
1842 trace_header("DTMF (not enabled by extension's settings)", DIRECTION_IN);
1847 if (e_state != EPOINT_STATE_IN_OVERLAP)
1849 trace_header("DTMF (ignored, not connected and not dialing)", DIRECTION_IN);
1853 if (!param->information.id[0])
1855 if (e_dialinginfo.id[0]=='\0' && !e_action)
1857 set_tone(portlist, "dialing");
1860 if (e_action->index==ACTION_OUTDIAL
1861 || e_action->index==ACTION_EXTERNAL)
1864 set_tone(portlist, "dialing");
1865 else if (!e_extdialing[0])
1866 set_tone(portlist, "dialing");
1868 /* concat dialing string */
1869 SCAT(e_dialinginfo.id, param->information.id);
1873 /* port MESSAGE_DTMF */
1874 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1876 /* only if dtmf detection is enabled */
1879 trace_header("DTMF (disabled)", DIRECTION_IN);
1883 trace_header("DTMF", DIRECTION_IN);
1884 add_trace("digit", NULL, "%c", param->dtmf);
1888 NOTE: vbox is now handled due to overlap state
1889 /* if vbox_play is done, the dtmf digits are just used as they come */
1891 if (e_action->index == ACTION_VBOX_PLAY)
1893 /* concat dialing string */
1894 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1896 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1897 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1900 /* continue to process *X# sequences */
1904 /* check for *X# sequence */
1905 if (e_state == EPOINT_STATE_CONNECT)
1907 if (e_dtmf_time+3 < now)
1909 /* the last digit was too far in the past to be a sequence */
1910 if (param->dtmf == '*')
1911 /* only start is allowed in the sequence */
1917 /* we have a sequence of digits, see what we got */
1918 if (param->dtmf == '*')
1920 else if (param->dtmf>='0' && param->dtmf<='9')
1922 /* we need to have a star before we receive the digit of the sequence */
1923 if (e_dtmf_last == '*')
1924 e_dtmf_last = param->dtmf;
1925 } else if (param->dtmf == '#')
1928 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1930 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1931 if (e_dtmf_last == '0')
1936 /* processing keypad function */
1938 keypad_function(e_dtmf_last);
1944 /* set last time of dtmf */
1949 /* check for ## hookflash during dialing */
1951 if (e_action->index==ACTION_PASSWORD
1952 || e_action->index==ACTION_PASSWORD_WRITE)
1954 if (param->dtmf=='#') /* current digit is '#' */
1956 if (e_state==EPOINT_STATE_IN_DISCONNECT
1957 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1974 /* dialing using dtmf digit */
1975 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1977 if (e_dialinginfo.id[0]=='\0' && !e_action)
1979 set_tone(portlist, "dialing");
1981 /* concat dialing string */
1982 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1984 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1985 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1991 /* port MESSAGE_CRYPT */
1992 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1994 /* send crypt response to cryptman */
1995 if (param->crypt.type == CR_MESSAGE_IND)
1996 cryptman_msg2man(param->crypt.data, param->crypt.len);
1998 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2001 /* port MESSAGE_OVERLAP */
2002 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
2004 struct message *message;
2006 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2008 /* signal to call tool */
2009 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
2011 if (e_dialing_queue[0] && portlist)
2013 /* send what we have not dialed yet, because we had no setup complete */
2014 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
2015 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2016 SCPY(message->param.information.id, e_dialing_queue);
2017 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
2018 message_put(message);
2019 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2020 e_dialing_queue[0] = '\0';
2022 /* check if pattern is available */
2023 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
2025 /* indicate patterns */
2026 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2027 message_put(message);
2029 /* connect audio, if not already */
2030 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2031 message->param.audiopath = CHANNEL_STATE_CONNECT;
2032 message_put(message);
2035 /* indicate no patterns */
2036 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2037 message_put(message);
2039 /* disconnect audio, if not already */
2040 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2041 message->param.audiopath = CHANNEL_STATE_HOLD;
2042 message_put(message);
2044 new_state(EPOINT_STATE_OUT_OVERLAP);
2045 /* if we are in a join */
2046 if (ea_endpoint->ep_join_id)
2048 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2049 memcpy(&message->param, param, sizeof(union parameter));
2050 message_put(message);
2054 /* port MESSAGE_PROCEEDING */
2055 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2057 struct message *message;
2059 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2061 /* signal to call tool */
2062 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
2064 e_state = EPOINT_STATE_OUT_PROCEEDING;
2065 /* check if pattern is availatle */
2066 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2068 /* indicate patterns */
2069 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2070 message_put(message);
2072 /* connect audio, if not already */
2073 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2074 message->param.audiopath = CHANNEL_STATE_CONNECT;
2075 message_put(message);
2078 /* indicate no patterns */
2079 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2080 message_put(message);
2082 /* disconnect audio, if not already */
2083 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2084 message->param.audiopath = CHANNEL_STATE_HOLD;
2085 message_put(message);
2087 /* if we are in a call */
2088 if (ea_endpoint->ep_join_id)
2090 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2091 memcpy(&message->param, param, sizeof(union parameter));
2092 message_put(message);
2096 /* port MESSAGE_ALERTING */
2097 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
2099 struct message *message;
2101 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2103 /* signal to call tool */
2104 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
2106 new_state(EPOINT_STATE_OUT_ALERTING);
2107 /* check if pattern is available */
2108 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2110 /* indicate patterns */
2111 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2112 message_put(message);
2114 /* connect audio, if not already */
2115 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2116 message->param.audiopath = CHANNEL_STATE_CONNECT;
2117 message_put(message);
2120 /* indicate no patterns */
2121 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2122 message_put(message);
2124 /* disconnect audio, if not already */
2125 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2126 message->param.audiopath = CHANNEL_STATE_HOLD;
2127 message_put(message);
2129 /* if we are in a call */
2130 if (ea_endpoint->ep_join_id)
2132 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2133 memcpy(&message->param, param, sizeof(union parameter));
2134 message_put(message);
2138 /* port MESSAGE_CONNECT */
2139 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2141 struct message *message;
2143 unsigned long port_id = portlist->port_id;
2144 struct port_list *tportlist;
2146 struct interface *interface;
2148 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2150 /* signal to call tool */
2151 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2153 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2154 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2155 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2157 tportlist = ea_endpoint->ep_portlist;
2158 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2159 tportlist = tportlist->next;
2160 if (tportlist->port_id == port_id)
2161 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2162 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2163 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2164 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2165 message_put(message);
2166 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2167 ea_endpoint->free_portlist(tportlist);
2169 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2173 /* screen incoming connected id */
2174 interface = interface_first;
2177 if (!strcmp(e_connectinfo.interface, interface->name))
2181 interface = interface->next;
2184 screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2186 /* screen connected name */
2188 SCPY(e_connectinfo.name, e_ext.name);
2190 /* add internal id to colp */
2191 SCPY(e_connectinfo.extension, e_ext.number);
2193 /* we store the connected port number */
2194 SCPY(e_extension_interface, e_connectinfo.interface);
2196 /* for internal and am calls, we get the extension's id */
2197 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2199 SCPY(e_connectinfo.id, e_ext.callerid);
2200 SCPY(e_connectinfo.extension, e_ext.number);
2201 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2202 e_connectinfo.ntype = e_ext.callerid_type;
2203 e_connectinfo.present = e_ext.callerid_present;
2205 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2207 e_connectinfo.itype = INFO_ITYPE_VBOX;
2208 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2211 new_state(EPOINT_STATE_CONNECT);
2213 /* set volume of rx and tx */
2214 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2216 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2217 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2218 message->param.mISDNsignal.rxvol = e_ext.txvol;
2219 message->param.mISDNsignal.txvol = e_ext.rxvol;
2220 message_put(message);
2223 e_cfnr_call = e_cfnr_release = 0;
2224 if (e_ext.number[0])
2225 e_dtmf = 1; /* allow dtmf */
2228 /* other calls with no caller id (or not available for the extension) and force colp */
2229 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2231 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2232 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2234 port = find_port_id(portlist->port_id);
2237 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype));
2238 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2243 /* send connect to join */
2244 if (ea_endpoint->ep_join_id)
2246 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2247 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2248 message_put(message);
2250 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2251 message->param.audiopath = CHANNEL_STATE_CONNECT;
2252 message_put(message);
2253 } else if (!e_adminid)
2256 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2257 SCPY(e_ext.number, e_cbcaller);
2258 new_state(EPOINT_STATE_IN_OVERLAP);
2259 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2261 /* get extension's info about terminal */
2262 if (!read_extension(&e_ext, e_ext.number))
2264 /* extension doesn't exist */
2265 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2266 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2267 new_state(EPOINT_STATE_OUT_DISCONNECT);
2268 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2272 /* put prefix in front of e_cbdialing */
2273 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2274 SCPY(e_dialinginfo.id, buffer);
2275 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2276 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2278 /* use caller id (or if exist: id_next_call) for this call */
2279 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2280 SCPY(e_callerinfo.extension, e_ext.number);
2281 if (e_ext.id_next_call_present >= 0)
2283 SCPY(e_callerinfo.id, e_ext.id_next_call);
2284 e_callerinfo.present = e_ext.id_next_call_present;
2285 e_callerinfo.ntype = e_ext.id_next_call_type;
2286 e_ext.id_next_call_present = -1;
2287 /* extension is written */
2288 write_extension(&e_ext, e_ext.number);
2291 SCPY(e_callerinfo.id, e_ext.callerid);
2292 e_callerinfo.present = e_ext.callerid_present;
2293 e_callerinfo.ntype = e_ext.callerid_type;
2296 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2299 /* check if caller id is NOT authenticated */
2300 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2302 /* make call state to enter password */
2303 new_state(EPOINT_STATE_IN_OVERLAP);
2304 e_action = &action_password_write;
2305 e_match_timeout = 0;
2306 e_match_to_action = NULL;
2307 e_dialinginfo.id[0] = '\0';
2308 e_extdialing = strchr(e_dialinginfo.id, '\0');
2309 e_password_timeout = now+20;
2313 /* incoming call (callback) */
2314 e_ruleset = ruleset_main;
2316 e_rule = e_ruleset->rule_first;
2318 e_extdialing = e_dialinginfo.id;
2319 if (e_dialinginfo.id[0])
2321 set_tone(portlist, "dialing");
2325 set_tone(portlist, "dialpbx");
2328 } else /* testcall */
2330 set_tone(portlist, "hold");
2333 /* start recording if enabled, not when answering machine answers */
2334 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))
2336 /* check if we are a terminal */
2337 if (e_ext.number[0] == '\0')
2338 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2341 port = find_port_id(portlist->port_id);
2343 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2348 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2349 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2351 struct message *message;
2353 unsigned long port_id = portlist->port_id;
2357 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2359 /* signal to call tool */
2360 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2362 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2363 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2365 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2370 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);
2371 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2372 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2374 /* check if we have more than one portlist relation and we just ignore the disconnect */
2375 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2377 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2378 portlist = ea_endpoint->ep_portlist;
2381 if (portlist->port_id == port_id)
2383 portlist = portlist->next;
2386 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2387 if (message_type != MESSAGE_RELEASE)
2389 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2390 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2391 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2392 message_put(message);
2393 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2395 ea_endpoint->free_portlist(portlist);
2396 return; /* one relation removed */
2398 if (e_state == EPOINT_STATE_CONNECT)
2400 /* use cause from port after connect */
2401 cause = param->disconnectinfo.cause;
2402 location = param->disconnectinfo.location;
2405 /* use multipoint cause if no connect yet */
2406 if (e_multipoint_cause)
2408 cause = e_multipoint_cause;
2409 location = e_multipoint_location;
2412 cause = CAUSE_NOUSER;
2413 location = LOCATION_PRIVATE_LOCAL;
2417 e_cfnr_call = e_cfnr_release = 0;
2419 /* process hangup */
2420 process_hangup(e_join_cause, e_join_location);
2421 e_multipoint_cause = 0;
2422 e_multipoint_location = 0;
2424 if (message_type == MESSAGE_DISCONNECT)
2426 /* tone to disconnected end */
2427 SPRINT(buffer, "cause_%02x", cause);
2428 if (ea_endpoint->ep_portlist)
2429 set_tone(ea_endpoint->ep_portlist, buffer);
2431 new_state(EPOINT_STATE_IN_DISCONNECT);
2434 if (ea_endpoint->ep_join_id)
2436 int haspatterns = 0;
2437 /* check if pattern is available */
2438 if (ea_endpoint->ep_portlist)
2439 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2440 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
2441 && message_type != MESSAGE_RELEASE) // if we release, we are done
2445 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2446 /* indicate patterns */
2447 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2448 message_put(message);
2449 /* connect audio, if not already */
2450 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2451 message->param.audiopath = CHANNEL_STATE_CONNECT;
2452 message_put(message);
2453 /* send disconnect */
2454 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2455 memcpy(&message->param, param, sizeof(union parameter));
2456 message_put(message);
2457 /* disable encryption if disconnected */
2458 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2460 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2464 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2467 if (message_type == MESSAGE_RELEASE)
2468 ea_endpoint->free_portlist(portlist);
2469 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2470 return; /* must exit here */
2473 /* port MESSAGE_TIMEOUT */
2474 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2478 trace_header("TIMEOUT", DIRECTION_IN);
2479 message_type = MESSAGE_DISCONNECT;
2480 switch (param->state)
2482 case PORT_STATE_OUT_SETUP:
2483 case PORT_STATE_OUT_OVERLAP:
2484 add_trace("state", NULL, "outgoing setup/dialing");
2486 /* no user responding */
2487 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2488 return; /* must exit here */
2490 case PORT_STATE_IN_SETUP:
2491 case PORT_STATE_IN_OVERLAP:
2492 add_trace("state", NULL, "incoming setup/dialing");
2493 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2494 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2497 case PORT_STATE_OUT_PROCEEDING:
2498 add_trace("state", NULL, "outgoing proceeding");
2500 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2501 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2502 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2503 return; /* must exit here */
2505 case PORT_STATE_IN_PROCEEDING:
2506 add_trace("state", NULL, "incoming proceeding");
2507 param->disconnectinfo.cause = CAUSE_NOUSER;
2508 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2511 case PORT_STATE_OUT_ALERTING:
2512 add_trace("state", NULL, "outgoing alerting");
2514 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2515 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2516 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2517 return; /* must exit here */
2519 case PORT_STATE_CONNECT:
2520 add_trace("state", NULL, "connect");
2522 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2523 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2524 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2525 return; /* must exit here */
2527 case PORT_STATE_IN_ALERTING:
2528 add_trace("state", NULL, "incoming alerting");
2529 param->disconnectinfo.cause = CAUSE_NOANSWER;
2530 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2533 case PORT_STATE_IN_DISCONNECT:
2534 case PORT_STATE_OUT_DISCONNECT:
2535 add_trace("state", NULL, "disconnect");
2537 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2538 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2539 return; /* must exit here */
2542 param->disconnectinfo.cause = 31; /* normal unspecified */
2543 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2546 /* release call, disconnect isdn */
2548 new_state(EPOINT_STATE_OUT_DISCONNECT);
2549 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2550 SCPY(e_tone, cause);
2553 set_tone(portlist, cause);
2554 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2555 portlist = portlist->next;
2557 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2560 /* port MESSAGE_NOTIFY */
2561 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2563 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2565 struct message *message;
2569 /* signal to call tool */
2570 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2571 if (param->notifyinfo.notify)
2573 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2576 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2577 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2579 case INFO_NOTIFY_REMOTE_HOLD:
2580 case INFO_NOTIFY_USER_SUSPENDED:
2581 /* tell call about it */
2582 if (ea_endpoint->ep_join_id)
2584 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2585 message->param.audiopath = CHANNEL_STATE_HOLD;
2586 message_put(message);
2590 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2591 case INFO_NOTIFY_USER_RESUMED:
2592 /* set volume of rx and tx */
2593 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2594 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2597 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2598 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2599 message->param.mISDNsignal.rxvol = e_ext.txvol;
2600 message->param.mISDNsignal.txvol = e_ext.rxvol;
2601 message_put(message);
2603 /* set current tone */
2605 set_tone(portlist, e_tone);
2606 /* tell call about it */
2607 if (ea_endpoint->ep_join_id)
2609 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2610 message->param.audiopath = CHANNEL_STATE_CONNECT;
2611 message_put(message);
2616 /* get name of notify */
2617 switch(param->notifyinfo.notify)
2623 logtext = "USER_SUSPENDED";
2626 logtext = "BEARER_SERVICE_CHANGED";
2629 logtext = "USER_RESUMED";
2632 logtext = "CONFERENCE_ESTABLISHED";
2635 logtext = "CONFERENCE_DISCONNECTED";
2638 logtext = "OTHER_PARTY_ADDED";
2641 logtext = "ISOLATED";
2644 logtext = "REATTACHED";
2647 logtext = "OTHER_PARTY_ISOLATED";
2650 logtext = "OTHER_PARTY_REATTACHED";
2653 logtext = "OTHER_PARTY_SPLIT";
2656 logtext = "OTHER_PARTY_DISCONNECTED";
2659 logtext = "CONFERENCE_FLOATING";
2662 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2665 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2668 logtext = "CALL_IS_A_WAITING_CALL";
2671 logtext = "DIVERSION_ACTIVATED";
2674 logtext = "RESERVED_CT_1";
2677 logtext = "RESERVED_CT_2";
2680 logtext = "REVERSE_CHARGING";
2683 logtext = "REMOTE_HOLD";
2686 logtext = "REMOTE_RETRIEVAL";
2689 logtext = "CALL_IS_DIVERTING";
2692 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2697 /* notify call if available */
2698 if (ea_endpoint->ep_join_id)
2700 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2701 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2702 message_put(message);
2707 /* port MESSAGE_FACILITY */
2708 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2710 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2712 struct message *message;
2714 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2715 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2716 message_put(message);
2719 /* port MESSAGE_SUSPEND */
2720 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2721 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2723 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2725 /* epoint is now parked */
2726 ea_endpoint->ep_park = 1;
2727 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2728 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2730 /* remove port relation */
2731 ea_endpoint->free_portlist(portlist);
2734 /* port MESSAGE_RESUME */
2735 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2736 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2738 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2740 /* epoint is now resumed */
2741 ea_endpoint->ep_park = 0;
2746 /* port sends message to the endpoint
2748 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2750 struct port_list *portlist;
2751 struct message *message;
2753 portlist = ea_endpoint->ep_portlist;
2756 if (port_id == portlist->port_id)
2758 portlist = portlist->next;
2762 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);
2766 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2767 switch(message_type)
2769 case MESSAGE_DATA: /* data from port */
2770 /* check if there is a call */
2771 if (!ea_endpoint->ep_join_id)
2773 /* continue if only one portlist */
2774 if (ea_endpoint->ep_portlist->next != NULL)
2776 /* forward message */
2777 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2780 case MESSAGE_TONE_EOF: /* tone is end of file */
2781 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2784 if (e_action->index == ACTION_VBOX_PLAY)
2788 if (e_action->index == ACTION_EFI)
2795 case MESSAGE_TONE_COUNTER: /* counter info received */
2796 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);
2798 if (e_action->index == ACTION_VBOX_PLAY)
2800 e_vbox_counter = param->counter.current;
2801 if (param->counter.max >= 0)
2802 e_vbox_counter_max = param->counter.max;
2806 /* PORT sends SETUP message */
2808 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);
2809 if (e_state!=EPOINT_STATE_IDLE)
2811 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2814 port_setup(portlist, message_type, param);
2817 /* PORT sends INFORMATION message */
2818 case MESSAGE_INFORMATION: /* additional digits received */
2819 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);
2820 port_information(portlist, message_type, param);
2823 /* PORT sends FACILITY message */
2824 case MESSAGE_FACILITY:
2825 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2826 port_facility(portlist, message_type, param);
2829 /* PORT sends DTMF message */
2830 case MESSAGE_DTMF: /* dtmf digits received */
2831 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);
2832 port_dtmf(portlist, message_type, param);
2835 /* PORT sends CRYPT message */
2836 case MESSAGE_CRYPT: /* crypt response received */
2837 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2838 port_crypt(portlist, message_type, param);
2841 /* PORT sends MORE message */
2842 case MESSAGE_OVERLAP:
2843 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);
2844 if (e_state != EPOINT_STATE_OUT_SETUP)
2846 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);
2849 port_overlap(portlist, message_type, param);
2852 /* PORT sends PROCEEDING message */
2853 case MESSAGE_PROCEEDING: /* port is proceeding */
2854 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);
2855 if (e_state!=EPOINT_STATE_OUT_SETUP
2856 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2858 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);
2861 port_proceeding(portlist, message_type, param);
2864 /* PORT sends ALERTING message */
2865 case MESSAGE_ALERTING:
2866 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);
2867 if (e_state!=EPOINT_STATE_OUT_SETUP
2868 && e_state!=EPOINT_STATE_OUT_OVERLAP
2869 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2871 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);
2874 port_alerting(portlist, message_type, param);
2877 /* PORT sends CONNECT message */
2878 case MESSAGE_CONNECT:
2879 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);
2880 if (e_state!=EPOINT_STATE_OUT_SETUP
2881 && e_state!=EPOINT_STATE_OUT_OVERLAP
2882 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2883 && e_state!=EPOINT_STATE_OUT_ALERTING)
2885 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2888 port_connect(portlist, message_type, param);
2891 /* PORT sends DISCONNECT message */
2892 case MESSAGE_DISCONNECT: /* port is disconnected */
2893 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);
2894 port_disconnect_release(portlist, message_type, param);
2897 /* PORT sends a RELEASE message */
2898 case MESSAGE_RELEASE: /* port releases */
2899 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);
2900 /* portlist is release at port_disconnect_release, thanx Paul */
2901 port_disconnect_release(portlist, message_type, param);
2904 /* PORT sends a TIMEOUT message */
2905 case MESSAGE_TIMEOUT:
2906 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);
2907 port_timeout(portlist, message_type, param);
2908 break; /* release */
2910 /* PORT sends a NOTIFY message */
2911 case MESSAGE_NOTIFY:
2912 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);
2913 port_notify(portlist, message_type, param);
2916 /* PORT sends a SUSPEND message */
2917 case MESSAGE_SUSPEND:
2918 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);
2919 port_suspend(portlist, message_type, param);
2920 break; /* suspend */
2922 /* PORT sends a RESUME message */
2923 case MESSAGE_RESUME:
2924 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);
2925 port_resume(portlist, message_type, param);
2929 /* port assigns bchannel */
2930 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2931 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);
2932 /* only one port is expected to be connected to bchannel */
2933 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2934 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2940 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);
2943 /* Note: this endpoint may be destroyed, so we MUST return */
2947 /* messages from join
2949 /* join MESSAGE_CRYPT */
2950 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2952 switch(param->crypt.type)
2954 /* message from remote port to "crypt manager" */
2955 case CU_ACTK_REQ: /* activate key-exchange */
2956 case CU_ACTS_REQ: /* activate shared key */
2957 case CU_DACT_REQ: /* deactivate */
2958 case CU_INFO_REQ: /* request last info message */
2959 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2962 /* message from "crypt manager" to user */
2963 case CU_ACTK_CONF: /* key-echange done */
2964 case CU_ACTS_CONF: /* shared key done */
2965 case CU_DACT_CONF: /* deactivated */
2966 case CU_DACT_IND: /* deactivated */
2967 case CU_ERROR_IND: /* receive error message */
2968 case CU_INFO_IND: /* receive info message */
2969 case CU_INFO_CONF: /* receive info message */
2970 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2974 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);
2978 /* join MESSAGE_INFORMATION */
2979 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2981 struct message *message;
2987 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2988 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2989 message_put(message);
2990 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2991 portlist = portlist->next;
2995 /* join MESSAGE_FACILITY */
2996 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2998 struct message *message;
3000 if (!e_ext.facility)
3007 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
3008 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
3009 message_put(message);
3010 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3011 portlist = portlist->next;
3015 /* join MESSAGE_MORE */
3016 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
3018 struct message *message;
3020 new_state(EPOINT_STATE_IN_OVERLAP);
3023 if (e_join_pattern && e_ext.own_setup)
3025 /* disconnect audio */
3026 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3027 message->param.audiopath = CHANNEL_STATE_HOLD;
3028 message_put(message);
3030 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3032 set_tone(portlist, "dialtone");
3035 if (e_ext.number[0])
3036 set_tone(portlist, "dialpbx");
3038 set_tone(portlist, "dialtone");
3041 /* join MESSAGE_PROCEEDING */
3042 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
3044 struct message *message;
3046 new_state(EPOINT_STATE_IN_PROCEEDING);
3048 /* own proceeding tone */
3051 /* connect / disconnect audio */
3052 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3053 if (e_ext.own_proceeding)
3054 message->param.audiopath = CHANNEL_STATE_HOLD;
3056 message->param.audiopath = CHANNEL_STATE_CONNECT;
3057 message_put(message);
3059 // UCPY(e_join_tone, "proceeding");
3062 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3063 message_put(message);
3064 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3066 set_tone(portlist, "proceeding");
3069 /* join MESSAGE_ALERTING */
3070 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
3072 struct message *message;
3074 new_state(EPOINT_STATE_IN_ALERTING);
3076 /* own alerting tone */
3079 /* connect / disconnect audio */
3080 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3081 if (e_ext.own_alerting)
3082 message->param.audiopath = CHANNEL_STATE_HOLD;
3084 message->param.audiopath = CHANNEL_STATE_CONNECT;
3085 message_put(message);
3089 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
3090 message_put(message);
3091 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3093 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3095 set_tone(portlist, "ringing");
3098 if (e_ext.number[0])
3099 set_tone(portlist, "ringpbx");
3101 set_tone(portlist, "ringing");
3104 /* join MESSAGE_CONNECT */
3105 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
3107 struct message *message;
3108 struct interface *interface;
3110 new_state(EPOINT_STATE_CONNECT);
3111 // UCPY(e_join_tone, "");
3112 if (e_ext.number[0])
3113 e_dtmf = 1; /* allow dtmf */
3115 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
3118 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3119 memcpy(&message->param, param, sizeof(union parameter));
3120 /* screen incoming caller id */
3121 interface = interface_first;
3124 if (!strcmp(e_connectinfo.interface, interface->name))
3128 interface = interface->next;
3131 screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
3132 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(e_connectinfo));
3134 /* screen clip if prefix is required */
3135 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3137 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3138 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
3139 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3142 /* use internal caller id */
3143 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3145 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
3146 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3149 /* handle restricted caller ids */
3150 apply_callerid_restriction(e_ext.anon_ignore, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
3151 /* display callerid if desired for extension */
3152 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));
3154 /* use conp, if enabld */
3156 message->param.connectinfo.name[0] = '\0';
3159 message_put(message);
3160 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3162 set_tone(portlist, NULL);
3164 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3165 message->param.audiopath = CHANNEL_STATE_CONNECT;
3166 message_put(message);
3170 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3171 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3174 struct message *message;
3175 struct port_list *portlist = NULL;
3178 /* be sure that we are active */
3180 e_tx_state = NOTIFY_STATE_ACTIVE;
3182 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3183 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3185 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3187 /* set time for power dialing */
3188 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3191 /* set redial tone */
3192 if (ea_endpoint->ep_portlist)
3196 set_tone(ea_endpoint->ep_portlist, "redial");
3197 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);
3198 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3199 if (e_state==EPOINT_STATE_IN_OVERLAP)
3201 new_state(EPOINT_STATE_IN_PROCEEDING);
3202 if (ea_endpoint->ep_portlist)
3204 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3205 message_put(message);
3206 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3208 /* caused the error, that the first knock sound was not there */
3209 /* set_tone(portlist, "proceeding"); */
3211 /* send display of powerdialing */
3212 if (e_ext.display_dialing)
3214 portlist = ea_endpoint->ep_portlist;
3217 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3219 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3221 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3222 message_put(message);
3223 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3224 portlist = portlist->next;
3233 if ((e_state!=EPOINT_STATE_CONNECT
3234 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3235 && e_state!=EPOINT_STATE_IN_OVERLAP
3236 && e_state!=EPOINT_STATE_IN_PROCEEDING
3237 && e_state!=EPOINT_STATE_IN_ALERTING)
3238 || !ea_endpoint->ep_portlist) /* or no port */
3240 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3241 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3242 return; /* must exit here */
3247 e_join_cause = param->disconnectinfo.cause;
3248 e_join_location = param->disconnectinfo.location;
3251 /* on release we need the audio again! */
3252 if (message_type == MESSAGE_RELEASE)
3255 ea_endpoint->ep_join_id = 0;
3257 /* disconnect and select tone */
3258 new_state(EPOINT_STATE_OUT_DISCONNECT);
3259 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3260 /* if own_cause, we must release the join */
3261 if (e_ext.own_cause /* own cause */
3262 || !e_join_pattern) /* no patterns */
3264 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);
3265 if (message_type != MESSAGE_RELEASE)
3266 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3268 } else /* else we enable audio */
3270 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3271 message->param.audiopath = CHANNEL_STATE_CONNECT;
3272 message_put(message);
3274 /* send disconnect message */
3275 SCPY(e_tone, cause);
3276 portlist = ea_endpoint->ep_portlist;
3279 set_tone(portlist, cause);
3280 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3281 portlist = portlist->next;
3285 /* join MESSAGE_SETUP */
3286 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3288 struct message *message;
3289 struct interface *interface;
3291 /* if we already in setup state, we just update the dialing with new digits */
3292 if (e_state == EPOINT_STATE_OUT_SETUP
3293 || e_state == EPOINT_STATE_OUT_OVERLAP)
3295 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3296 /* if digits changed, what we have already dialed */
3297 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3299 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);
3300 /* release all ports */
3301 while((portlist = ea_endpoint->ep_portlist))
3303 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3304 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3305 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3306 message_put(message);
3307 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3308 ea_endpoint->free_portlist(portlist);
3311 /* disconnect audio */
3312 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3313 message->param.audiopath = CHANNEL_STATE_HOLD;
3314 message_put(message);
3316 /* get dialing info */
3317 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3318 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3319 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3320 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3321 new_state(EPOINT_STATE_OUT_OVERLAP);
3324 e_redial = now_d + 1; /* set redial one second in the future */
3327 /* if we have a pending redial, so we just adjust the dialing number */
3330 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);
3331 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3334 if (!ea_endpoint->ep_portlist)
3336 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3338 if (ea_endpoint->ep_portlist->next)
3340 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3342 if (e_state == EPOINT_STATE_OUT_SETUP)
3345 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);
3346 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3350 /* get what we have not dialed yet */
3351 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));
3352 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3353 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3354 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3355 message_put(message);
3356 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3358 /* always store what we have dialed or queued */
3359 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3363 if (e_state != EPOINT_STATE_IDLE)
3365 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3368 /* if an internal extension is dialed, copy that number */
3369 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3370 SCPY(e_ext.number, param->setup.dialinginfo.id);
3371 /* if an internal extension is dialed, get extension's info about caller */
3372 if (e_ext.number[0])
3374 if (!read_extension(&e_ext, e_ext.number))
3376 e_ext.number[0] = '\0';
3377 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3381 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3382 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3383 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3384 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3386 /* screen incoming caller id */
3387 interface = interface_first;
3390 if (!strcmp(e_callerinfo.interface, interface->name))
3394 interface = interface->next;
3397 screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
3399 /* process (voice over) data calls */
3400 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3402 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3403 memset(&e_capainfo, 0, sizeof(e_capainfo));
3404 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3405 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3406 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3409 new_state(EPOINT_STATE_OUT_SETUP);
3410 /* call special setup routine */
3414 /* join MESSAGE_mISDNSIGNAL */
3415 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3417 struct message *message;
3421 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3422 memcpy(&message->param, param, sizeof(union parameter));
3423 message_put(message);
3424 portlist = portlist->next;
3428 /* join MESSAGE_NOTIFY */
3429 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3431 struct message *message;
3434 if (param->notifyinfo.notify)
3436 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3437 // /* if notification was generated locally, we turn hold music on/off */
3438 // if (param->notifyinfo.local)
3439 // 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)
3444 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3448 set_tone(portlist, "");
3449 portlist = portlist->next;
3451 portlist = ea_endpoint->ep_portlist;
3456 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3460 set_tone(portlist, "hold");
3461 portlist = portlist->next;
3463 portlist = ea_endpoint->ep_portlist;
3468 /* save new state */
3469 e_tx_state = new_state;
3472 /* notify port(s) about it */
3475 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3476 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3477 /* handle restricted caller ids */
3478 apply_callerid_restriction(e_ext.anon_ignore, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3479 /* display callerid if desired for extension */
3480 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));
3481 message_put(message);
3482 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3483 portlist = portlist->next;
3487 /* JOIN sends messages to the endpoint
3489 void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, union parameter *param)
3491 struct port_list *portlist;
3492 struct message *message;
3496 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3500 portlist = ea_endpoint->ep_portlist;
3502 /* send MESSAGE_DATA to port */
3503 if (message_type == MESSAGE_DATA)
3505 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3507 /* skip if no port relation */
3510 /* skip if more than one port relation */
3513 /* forward audio data to port */
3514 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3519 // 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);
3520 switch(message_type)
3522 /* JOIN SENDS TONE message */
3524 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);
3525 set_tone(portlist, param->tone.name);
3528 /* JOIN SENDS CRYPT message */
3530 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);
3531 join_crypt(portlist, message_type, param);
3534 /* JOIN sends INFORMATION message */
3535 case MESSAGE_INFORMATION:
3536 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);
3537 join_information(portlist, message_type, param);
3540 /* JOIN sends FACILITY message */
3541 case MESSAGE_FACILITY:
3542 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);
3543 join_facility(portlist, message_type, param);
3546 /* JOIN sends OVERLAP message */
3547 case MESSAGE_OVERLAP:
3548 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);
3549 if (e_state!=EPOINT_STATE_IN_SETUP
3550 && e_state!=EPOINT_STATE_IN_OVERLAP)
3552 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3555 join_overlap(portlist, message_type, param);
3558 /* JOIN sends PROCEEDING message */
3559 case MESSAGE_PROCEEDING:
3560 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);
3561 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3563 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3566 join_proceeding(portlist, message_type, param);
3569 /* JOIN sends ALERTING message */
3570 case MESSAGE_ALERTING:
3571 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);
3572 if (e_state!=EPOINT_STATE_IN_OVERLAP
3573 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3575 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3578 join_alerting(portlist, message_type, param);
3581 /* JOIN sends CONNECT message */
3582 case MESSAGE_CONNECT:
3583 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);
3584 if (e_state!=EPOINT_STATE_IN_OVERLAP
3585 && e_state!=EPOINT_STATE_IN_PROCEEDING
3586 && e_state!=EPOINT_STATE_IN_ALERTING)
3588 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3591 join_connect(portlist, message_type, param);
3594 /* JOIN sends DISCONNECT/RELEASE message */
3595 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3596 case MESSAGE_RELEASE: /* JOIN releases */
3597 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);
3598 join_disconnect_release(message_type, param);
3601 /* JOIN sends SETUP message */
3603 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);
3604 join_setup(portlist, message_type, param);
3607 /* JOIN sends special mISDNSIGNAL message */
3608 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3609 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);
3610 join_mISDNsignal(portlist, message_type, param);
3614 /* JOIN requests bchannel */
3615 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3616 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);
3617 /* only one port is expected to be connected to bchannel */
3624 set_tone(portlist, NULL);
3625 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3626 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3630 /* JOIN has pattern available */
3631 case MESSAGE_PATTERN: /* indicating pattern available */
3632 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);
3633 if (!e_join_pattern)
3635 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3640 set_tone(portlist, NULL);
3641 portlist = portlist->next;
3643 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3644 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3645 message->param.audiopath = CHANNEL_STATE_CONNECT;
3646 message_put(message);
3647 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3648 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_REMOTE_AUDIO);
3649 // message->param.audiopath = CHANNEL_STATE_CONNECT;
3650 // message_put(message);
3651 // patterns are available, remote already connected audio
3655 /* JOIN has no pattern available */
3656 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3657 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);
3660 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3662 /* disconnect our audio tx and rx */
3663 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3664 message->param.audiopath = CHANNEL_STATE_HOLD;
3665 message_put(message);
3670 /* JOIN (dunno at the moment) */
3671 case MESSAGE_REMOTE_AUDIO:
3672 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);
3673 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3674 message->param.audiopath = param->channel;
3675 message_put(message);
3679 /* JOIN sends a notify message */
3680 case MESSAGE_NOTIFY:
3681 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);
3682 join_notify(portlist, message_type, param);
3686 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);
3691 /* pick_join will connect the first incoming call found. the endpoint
3692 * will receivce a MESSAGE_CONNECT.
3694 int match_list(char *list, char *item)
3696 char *end, *next = NULL;
3698 /* no list make matching */
3704 /* eliminate white spaces */
3705 while (*list <= ' ')
3712 /* if end of list is reached, we return */
3713 if (list[0] == '\0')
3715 /* if we have more than one entry (left) */
3716 if ((end = strchr(list, ',')))
3719 next = end = strchr(list, '\0');
3720 while (*(end-1) <= ' ')
3722 /* if string part matches item */
3723 if (!strncmp(list, item, end-list))
3729 void EndpointAppPBX::pick_join(char *extensions)
3731 struct message *message;
3732 struct port_list *portlist;
3734 class EndpointAppPBX *eapp, *found;
3736 class JoinPBX *joinpbx;
3737 struct join_relation *relation;
3740 /* find an endpoint that is ringing internally or vbox with higher priority */
3743 eapp = apppbx_first;
3746 if (eapp!=this && ea_endpoint->ep_portlist)
3748 portlist = eapp->ea_endpoint->ep_portlist;
3751 if ((port = find_port_id(portlist->port_id)))
3753 if (port->p_type == PORT_TYPE_VBOX_OUT)
3755 if (match_list(extensions, eapp->e_ext.number))
3762 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3763 && port->p_state==PORT_STATE_OUT_ALERTING)
3764 if (match_list(extensions, eapp->e_ext.number))
3769 portlist = portlist->next;
3777 /* if no endpoint found */
3780 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);
3782 set_tone(ea_endpoint->ep_portlist, "cause_10");
3783 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3784 new_state(EPOINT_STATE_OUT_DISCONNECT);
3789 if (ea_endpoint->ep_join_id)
3791 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3794 if (!eapp->ea_endpoint->ep_join_id)
3796 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3799 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3802 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3805 if (join->j_type != JOIN_TYPE_PBX)
3807 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3810 joinpbx = (class JoinPBX *)join;
3811 relation = joinpbx->j_relation;
3814 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3817 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3819 relation = relation->next;
3822 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3827 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3829 if (options.deb & DEBUG_EPOINT)
3831 class Join *debug_c = join_first;
3832 class Endpoint *debug_e = epoint_first;
3833 class Port *debug_p = port_first;
3835 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3837 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3840 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3841 debug_c = debug_c->next;
3843 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3846 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3847 debug_e = debug_e->next;
3849 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3852 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3853 debug_p = debug_p->next;
3858 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3859 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3860 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3862 /* connnecting our endpoint */
3863 new_state(EPOINT_STATE_CONNECT);
3865 set_tone(ea_endpoint->ep_portlist, NULL);
3867 /* now we send a release to the ringing endpoint */
3868 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3869 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3870 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3871 message_put(message);
3873 /* we send a connect to the join with our caller id */
3874 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3875 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3876 message->param.connectinfo.present = e_callerinfo.present;
3877 message->param.connectinfo.screen = e_callerinfo.screen;
3878 message->param.connectinfo.itype = e_callerinfo.itype;
3879 message->param.connectinfo.ntype = e_callerinfo.ntype;
3880 message_put(message);
3882 /* we send a connect to our port with the remote callerid */
3883 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3884 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3885 message->param.connectinfo.present = eapp->e_callerinfo.present;
3886 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3887 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3888 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3889 /* handle restricted caller ids */
3890 apply_callerid_restriction(e_ext.anon_ignore, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
3891 /* display callerid if desired for extension */
3892 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));
3893 message_put(message);
3895 /* we send a connect to the audio path (not for vbox) */
3896 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3897 message->param.audiopath = CHANNEL_STATE_CONNECT;
3898 message_put(message);
3900 /* beeing paranoid, we make call update */
3901 joinpbx->j_updatebridge = 1;
3903 if (options.deb & DEBUG_EPOINT)
3905 class Join *debug_c = join_first;
3906 class Endpoint *debug_e = epoint_first;
3907 class Port *debug_p = port_first;
3909 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3911 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3914 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3915 debug_c = debug_c->next;
3917 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3920 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3921 debug_e = debug_e->next;
3923 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3926 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3927 debug_p = debug_p->next;
3933 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3935 void EndpointAppPBX::join_join(void)
3937 struct message *message;
3938 struct join_relation *our_relation, *other_relation;
3939 struct join_relation **our_relation_pointer, **other_relation_pointer;
3940 class Join *our_join, *other_join;
3941 class JoinPBX *our_joinpbx, *other_joinpbx;
3942 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3943 class Port *our_port, *other_port;
3944 class Pdss1 *our_pdss1, *other_pdss1;
3946 /* are we a candidate to join a join */
3947 our_join = find_join_id(ea_endpoint->ep_join_id);
3950 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3953 if (our_join->j_type != JOIN_TYPE_PBX)
3955 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3958 our_joinpbx = (class JoinPBX *)our_join;
3959 if (!ea_endpoint->ep_portlist)
3961 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3964 if (!e_ext.number[0])
3966 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3969 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3972 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3975 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3977 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3980 our_pdss1 = (class Pdss1 *)our_port;
3982 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3983 other_eapp = apppbx_first;
3986 if (other_eapp == this)
3988 other_eapp = other_eapp->next;
3991 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);
3992 if (other_eapp->e_ext.number[0] /* has terminal */
3993 && other_eapp->ea_endpoint->ep_portlist /* has port */
3994 && other_eapp->ea_endpoint->ep_join_id) /* has join */
3996 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3997 if (other_port) /* port still exists */
3999 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
4000 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
4002 other_pdss1 = (class Pdss1 *)other_port;
4003 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);
4004 if (other_pdss1->p_m_hold /* port is on hold */
4005 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
4006 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
4010 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
4014 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
4017 other_eapp = other_eapp->next;
4021 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
4024 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
4026 /* if we have the same join */
4027 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
4029 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
4032 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
4035 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
4038 if (other_join->j_type != JOIN_TYPE_PBX)
4040 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
4043 other_joinpbx = (class JoinPBX *)other_join;
4044 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
4046 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
4050 /* remove relation to endpoint for join on hold */
4051 other_relation = other_joinpbx->j_relation;
4052 other_relation_pointer = &other_joinpbx->j_relation;
4053 while(other_relation)
4055 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
4057 /* detach other endpoint on hold */
4058 *other_relation_pointer = other_relation->next;
4059 FREE(other_relation, sizeof(struct join_relation));
4061 other_relation = *other_relation_pointer;
4062 other_eapp->ea_endpoint->ep_join_id = NULL;
4066 /* change join/hold pointer of endpoint to the new join */
4067 temp_epoint = find_epoint_id(other_relation->epoint_id);
4070 if (temp_epoint->ep_join_id == other_join->j_serial)
4071 temp_epoint->ep_join_id = our_join->j_serial;
4074 other_relation_pointer = &other_relation->next;
4075 other_relation = other_relation->next;
4077 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
4079 /* join call relations */
4080 our_relation = our_joinpbx->j_relation;
4081 our_relation_pointer = &our_joinpbx->j_relation;
4084 our_relation_pointer = &our_relation->next;
4085 our_relation = our_relation->next;
4087 *our_relation_pointer = other_joinpbx->j_relation;
4088 other_joinpbx->j_relation = NULL;
4089 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
4091 /* release endpoint on hold */
4092 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
4093 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
4094 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
4095 message_put(message);
4097 /* if we are not a partyline, we get partyline state from other join */
4098 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
4100 /* remove empty join */
4102 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
4104 /* mixer must update */
4105 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
4107 /* we send a retrieve to that endpoint */
4108 // mixer will update the hold-state of the join and send it to the endpoints is changes
4112 /* check if we have an external call
4113 * this is used to check for encryption ability
4115 int EndpointAppPBX::check_external(char **errstr, class Port **port)
4117 struct join_relation *relation;
4119 class JoinPBX *joinpbx;
4120 class Endpoint *epoint;
4122 /* some paranoia check */
4123 if (!ea_endpoint->ep_portlist)
4125 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4126 *errstr = "No Call";
4129 if (!e_ext.number[0])
4131 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4132 *errstr = "No Call";
4136 /* check if we have a join with 2 parties */
4137 join = find_join_id(ea_endpoint->ep_join_id);
4140 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
4141 *errstr = "No Call";
4144 if (join->j_type != JOIN_TYPE_PBX)
4146 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
4147 *errstr = "No PBX Call";
4150 joinpbx = (class JoinPBX *)join;
4151 relation = joinpbx->j_relation;
4154 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
4155 *errstr = "No Call";
4158 if (!relation->next)
4160 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
4161 *errstr = "No Call";
4164 if (relation->next->next)
4166 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4167 *errstr = "Err: Conference";
4170 if (relation->epoint_id == ea_endpoint->ep_serial)
4172 relation = relation->next;
4173 if (relation->epoint_id == ea_endpoint->ep_serial)
4175 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4176 *errstr = "Software Error";
4181 /* check remote port for external call */
4182 epoint = find_epoint_id(relation->epoint_id);
4185 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4186 *errstr = "No Call";
4189 if (!epoint->ep_portlist)
4191 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4192 *errstr = "No Call";
4195 *port = find_port_id(epoint->ep_portlist->port_id);
4198 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4199 *errstr = "No Call";
4202 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4204 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4205 *errstr = "No Ext Call";
4208 if ((*port)->p_state != PORT_STATE_CONNECT)
4210 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4211 *errstr = "No Ext Connect";
4217 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned long port_id, int dir)
4219 char *logtext = "unknown";
4222 switch(message_type)
4225 trace_header("SETUP", dir);
4226 if (dir == DIRECTION_OUT)
4227 add_trace("to", NULL, "CH(%lu)", port_id);
4228 if (dir == DIRECTION_IN)
4229 add_trace("from", NULL, "CH(%lu)", port_id);
4230 if (param->setup.callerinfo.extension[0])
4231 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4232 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype));
4233 switch(param->setup.callerinfo.present)
4235 case INFO_PRESENT_RESTRICTED:
4236 add_trace("caller id", "present", "restricted");
4238 case INFO_PRESENT_ALLOWED:
4239 add_trace("caller id", "present", "allowed");
4242 add_trace("caller id", "present", "not available");
4244 if (param->setup.redirinfo.id[0])
4246 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype));
4247 switch(param->setup.redirinfo.present)
4249 case INFO_PRESENT_RESTRICTED:
4250 add_trace("redir'ing", "present", "restricted");
4252 case INFO_PRESENT_ALLOWED:
4253 add_trace("redir'ing", "present", "allowed");
4256 add_trace("redir'ing", "present", "not available");
4259 if (param->setup.dialinginfo.id[0])
4260 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4264 case MESSAGE_OVERLAP:
4265 trace_header("SETUP ACKNOWLEDGE", dir);
4266 if (dir == DIRECTION_OUT)
4267 add_trace("to", NULL, "CH(%lu)", port_id);
4268 if (dir == DIRECTION_IN)
4269 add_trace("from", NULL, "CH(%lu)", port_id);
4273 case MESSAGE_PROCEEDING:
4274 trace_header("PROCEEDING", dir);
4275 if (dir == DIRECTION_OUT)
4276 add_trace("to", NULL, "CH(%lu)", port_id);
4277 if (dir == DIRECTION_IN)
4278 add_trace("from", NULL, "CH(%lu)", port_id);
4282 case MESSAGE_ALERTING:
4283 trace_header("ALERTING", dir);
4284 if (dir == DIRECTION_OUT)
4285 add_trace("to", NULL, "CH(%lu)", port_id);
4286 if (dir == DIRECTION_IN)
4287 add_trace("from", NULL, "CH(%lu)", port_id);
4291 case MESSAGE_CONNECT:
4292 trace_header("CONNECT", dir);
4293 if (dir == DIRECTION_OUT)
4294 add_trace("to", NULL, "CH(%lu)", port_id);
4295 if (dir == DIRECTION_IN)
4296 add_trace("from", NULL, "CH(%lu)", port_id);
4297 if (param->connectinfo.extension[0])
4298 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4299 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype));
4300 switch(param->connectinfo.present)
4302 case INFO_PRESENT_RESTRICTED:
4303 add_trace("connect id", "present", "restricted");
4305 case INFO_PRESENT_ALLOWED:
4306 add_trace("connect id", "present", "allowed");
4309 add_trace("connect id", "present", "not available");
4314 case MESSAGE_DISCONNECT:
4315 case MESSAGE_RELEASE:
4316 if (message_type == MESSAGE_DISCONNECT)
4317 trace_header("DISCONNECT", dir);
4319 trace_header("RELEASE", dir);
4320 if (dir == DIRECTION_OUT)
4321 add_trace("to", NULL, "CH(%lu)", port_id);
4322 if (dir == DIRECTION_IN)
4323 add_trace("from", NULL, "CH(%lu)", port_id);
4324 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4325 switch(param->disconnectinfo.location)
4328 add_trace("cause", "location", "0-User");
4330 case LOCATION_PRIVATE_LOCAL:
4331 add_trace("cause", "location", "1-Local-PBX");
4333 case LOCATION_PUBLIC_LOCAL:
4334 add_trace("cause", "location", "2-Local-Exchange");
4336 case LOCATION_TRANSIT:
4337 add_trace("cause", "location", "3-Transit");
4339 case LOCATION_PUBLIC_REMOTE:
4340 add_trace("cause", "location", "4-Remote-PBX");
4342 case LOCATION_PRIVATE_REMOTE:
4343 add_trace("cause", "location", "5-Remote-Exchange");
4345 case LOCATION_INTERNATIONAL:
4346 add_trace("cause", "location", "7-International-Exchange");
4348 case LOCATION_BEYOND:
4349 add_trace("cause", "location", "10-Beyond-Interworking");
4352 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4357 case MESSAGE_NOTIFY:
4358 switch(param->notifyinfo.notify)
4364 logtext = "USER_SUSPENDED";
4367 logtext = "BEARER_SERVICE_CHANGED";
4370 logtext = "USER_RESUMED";
4373 logtext = "CONFERENCE_ESTABLISHED";
4376 logtext = "CONFERENCE_DISCONNECTED";
4379 logtext = "OTHER_PARTY_ADDED";
4382 logtext = "ISOLATED";
4385 logtext = "REATTACHED";
4388 logtext = "OTHER_PARTY_ISOLATED";
4391 logtext = "OTHER_PARTY_REATTACHED";
4394 logtext = "OTHER_PARTY_SPLIT";
4397 logtext = "OTHER_PARTY_DISCONNECTED";
4400 logtext = "CONFERENCE_FLOATING";
4403 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4406 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4409 logtext = "CALL_IS_A_WAITING_CALL";
4412 logtext = "DIVERSION_ACTIVATED";
4415 logtext = "RESERVED_CT_1";
4418 logtext = "RESERVED_CT_2";
4421 logtext = "REVERSE_CHARGING";
4424 logtext = "REMOTE_HOLD";
4427 logtext = "REMOTE_RETRIEVAL";
4430 logtext = "CALL_IS_DIVERTING";
4433 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4437 trace_header("NOTIFY", dir);
4438 if (dir == DIRECTION_OUT)
4439 add_trace("to", NULL, "CH(%lu)", port_id);
4440 if (dir == DIRECTION_IN)
4441 add_trace("from", NULL, "CH(%lu)", port_id);
4442 if (param->notifyinfo.notify)
4443 add_trace("indicator", NULL, "%s", logtext);
4444 if (param->notifyinfo.id[0])
4446 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype));
4447 switch(param->notifyinfo.present)
4449 case INFO_PRESENT_RESTRICTED:
4450 add_trace("redir'on", "present", "restricted");
4452 case INFO_PRESENT_ALLOWED:
4453 add_trace("redir'on", "present", "allowed");
4456 add_trace("redir'on", "present", "not available");
4459 if (param->notifyinfo.display[0])
4460 add_trace("display", NULL, "%s", param->notifyinfo.display);
4464 case MESSAGE_INFORMATION:
4465 trace_header("INFORMATION", dir);
4466 if (dir == DIRECTION_OUT)
4467 add_trace("to", NULL, "CH(%lu)", port_id);
4468 if (dir == DIRECTION_IN)
4469 add_trace("from", NULL, "CH(%lu)", port_id);
4470 add_trace("dialing", NULL, "%s", param->information.id);
4474 case MESSAGE_FACILITY:
4475 trace_header("FACILITY", dir);
4476 if (dir == DIRECTION_OUT)
4477 add_trace("to", NULL, "CH(%lu)", port_id);
4478 if (dir == DIRECTION_IN)
4479 add_trace("from", NULL, "CH(%lu)", port_id);
4484 trace_header("TONE", dir);
4485 if (dir == DIRECTION_OUT)
4486 add_trace("to", NULL, "CH(%lu)", port_id);
4487 if (dir == DIRECTION_IN)
4488 add_trace("from", NULL, "CH(%lu)", port_id);
4489 if (param->tone.name[0])
4491 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4492 add_trace("name", NULL, "%s", param->tone.name);
4494 add_trace("off", NULL, NULL);
4498 case MESSAGE_SUSPEND:
4499 case MESSAGE_RESUME:
4500 if (message_type == MESSAGE_SUSPEND)
4501 trace_header("SUSPEND", dir);
4503 trace_header("RESUME", dir);
4504 if (dir == DIRECTION_OUT)
4505 add_trace("to", NULL, "CH(%lu)", port_id);
4506 if (dir == DIRECTION_IN)
4507 add_trace("from", NULL, "CH(%lu)", port_id);
4508 if (param->parkinfo.len)
4509 add_trace("length", NULL, "%d", param->parkinfo.len);
4514 case MESSAGE_BCHANNEL:
4515 trace_header("BCHANNEL", dir);
4516 switch(param->bchannel.type)
4518 case BCHANNEL_REQUEST:
4519 add_trace("type", NULL, "request");
4521 case BCHANNEL_ASSIGN:
4522 add_trace("type", NULL, "assign");
4524 case BCHANNEL_ASSIGN_ACK:
4525 add_trace("type", NULL, "assign_ack");
4527 case BCHANNEL_REMOVE:
4528 add_trace("type", NULL, "remove");
4530 case BCHANNEL_REMOVE_ACK:
4531 add_trace("type", NULL, "remove_ack");
4534 if (param->bchannel.addr)
4535 add_trace("address", NULL, "%x", param->bchannel.addr);
4541 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4545 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4547 struct message *message;
4551 if (!portlist->port_id)
4554 if (!e_connectedmode)
4556 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4557 message->param.disconnectinfo.cause = cause;
4558 message->param.disconnectinfo.location = location;
4560 SCPY(message->param.disconnectinfo.display, display);
4562 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4565 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4567 SCPY(message->param.notifyinfo.display, display);
4569 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4571 message_put(message);
4572 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);