1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 #include <sys/types.h>
23 class EndpointAppPBX *apppbx_first = NULL;
26 * EndpointAppPBX constructor
28 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
30 class EndpointAppPBX **apppointer;
32 /* add application to chain */
34 apppointer = &apppbx_first;
36 apppointer = &((*apppointer)->next);
40 memset(&e_ext, 0, sizeof(struct extension));
41 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);
314 *strchr(id,'%') = '\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 if (e_ext.number[0])
1843 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1845 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1850 if (e_state != EPOINT_STATE_IN_OVERLAP)
1852 if (e_ext.number[0])
1853 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1855 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1859 if (!param->information.id[0])
1861 if (e_dialinginfo.id[0]=='\0' && !e_action)
1863 set_tone(portlist, "dialing");
1866 if (e_action->index==ACTION_OUTDIAL
1867 || e_action->index==ACTION_EXTERNAL)
1870 set_tone(portlist, "dialing");
1871 else if (!e_extdialing[0])
1872 set_tone(portlist, "dialing");
1874 /* concat dialing string */
1875 SCAT(e_dialinginfo.id, param->information.id);
1879 /* port MESSAGE_DTMF */
1880 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1882 /* only if dtmf detection is enabled */
1885 trace_header("DTMF (disabled)", DIRECTION_IN);
1889 trace_header("DTMF", DIRECTION_IN);
1890 add_trace("digit", NULL, "%c", param->dtmf);
1894 NOTE: vbox is now handled due to overlap state
1895 /* if vbox_play is done, the dtmf digits are just used as they come */
1897 if (e_action->index == ACTION_VBOX_PLAY)
1899 /* concat dialing string */
1900 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1902 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1903 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1906 /* continue to process *X# sequences */
1910 /* check for *X# sequence */
1911 if (e_state == EPOINT_STATE_CONNECT)
1913 if (e_dtmf_time+3 < now)
1915 /* the last digit was too far in the past to be a sequence */
1916 if (param->dtmf == '*')
1917 /* only start is allowed in the sequence */
1923 /* we have a sequence of digits, see what we got */
1924 if (param->dtmf == '*')
1926 else if (param->dtmf>='0' && param->dtmf<='9')
1928 /* we need to have a star before we receive the digit of the sequence */
1929 if (e_dtmf_last == '*')
1930 e_dtmf_last = param->dtmf;
1931 } else if (param->dtmf == '#')
1934 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1936 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1937 if (e_dtmf_last == '0')
1942 /* processing keypad function */
1944 keypad_function(e_dtmf_last);
1950 /* set last time of dtmf */
1955 /* check for ## hookflash during dialing */
1957 if (e_action->index==ACTION_PASSWORD
1958 || e_action->index==ACTION_PASSWORD_WRITE)
1960 if (param->dtmf=='#') /* current digit is '#' */
1962 if (e_state==EPOINT_STATE_IN_DISCONNECT
1963 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1980 /* dialing using dtmf digit */
1981 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1983 if (e_dialinginfo.id[0]=='\0' && !e_action)
1985 set_tone(portlist, "dialing");
1987 /* concat dialing string */
1988 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1990 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1991 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1997 /* port MESSAGE_CRYPT */
1998 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
2000 /* send crypt response to cryptman */
2001 if (param->crypt.type == CR_MESSAGE_IND)
2002 cryptman_msg2man(param->crypt.data, param->crypt.len);
2004 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2007 /* port MESSAGE_OVERLAP */
2008 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
2010 struct message *message;
2012 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2014 /* signal to call tool */
2015 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
2017 if (e_dialing_queue[0] && portlist)
2019 /* send what we have not dialed yet, because we had no setup complete */
2020 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
2021 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2022 SCPY(message->param.information.id, e_dialing_queue);
2023 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
2024 message_put(message);
2025 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2026 e_dialing_queue[0] = '\0';
2028 /* check if pattern is available */
2029 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
2031 /* indicate patterns */
2032 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2033 message_put(message);
2035 /* connect audio, if not already */
2036 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2037 message->param.audiopath = CHANNEL_STATE_CONNECT;
2038 message_put(message);
2041 /* indicate no patterns */
2042 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2043 message_put(message);
2045 /* disconnect audio, if not already */
2046 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2047 message->param.audiopath = CHANNEL_STATE_HOLD;
2048 message_put(message);
2050 new_state(EPOINT_STATE_OUT_OVERLAP);
2051 /* if we are in a join */
2052 if (ea_endpoint->ep_join_id)
2054 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2055 memcpy(&message->param, param, sizeof(union parameter));
2056 message_put(message);
2060 /* port MESSAGE_PROCEEDING */
2061 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2063 struct message *message;
2065 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2067 /* signal to call tool */
2068 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
2070 e_state = EPOINT_STATE_OUT_PROCEEDING;
2071 /* check if pattern is availatle */
2072 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2074 /* indicate patterns */
2075 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2076 message_put(message);
2078 /* connect audio, if not already */
2079 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2080 message->param.audiopath = CHANNEL_STATE_CONNECT;
2081 message_put(message);
2084 /* indicate no patterns */
2085 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2086 message_put(message);
2088 /* disconnect audio, if not already */
2089 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2090 message->param.audiopath = CHANNEL_STATE_HOLD;
2091 message_put(message);
2093 /* if we are in a call */
2094 if (ea_endpoint->ep_join_id)
2096 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2097 memcpy(&message->param, param, sizeof(union parameter));
2098 message_put(message);
2102 /* port MESSAGE_ALERTING */
2103 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
2105 struct message *message;
2107 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2109 /* signal to call tool */
2110 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
2112 new_state(EPOINT_STATE_OUT_ALERTING);
2113 /* check if pattern is available */
2114 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2116 /* indicate patterns */
2117 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2118 message_put(message);
2120 /* connect audio, if not already */
2121 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2122 message->param.audiopath = CHANNEL_STATE_CONNECT;
2123 message_put(message);
2126 /* indicate no patterns */
2127 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2128 message_put(message);
2130 /* disconnect audio, if not already */
2131 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2132 message->param.audiopath = CHANNEL_STATE_HOLD;
2133 message_put(message);
2135 /* if we are in a call */
2136 if (ea_endpoint->ep_join_id)
2138 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2139 memcpy(&message->param, param, sizeof(union parameter));
2140 message_put(message);
2144 /* port MESSAGE_CONNECT */
2145 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2147 struct message *message;
2149 unsigned long port_id = portlist->port_id;
2150 struct port_list *tportlist;
2152 struct interface *interface;
2154 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2156 /* signal to call tool */
2157 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2159 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2160 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2161 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2163 tportlist = ea_endpoint->ep_portlist;
2164 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2165 tportlist = tportlist->next;
2166 if (tportlist->port_id == port_id)
2167 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2168 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2169 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2170 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2171 message_put(message);
2172 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2173 ea_endpoint->free_portlist(tportlist);
2175 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2179 /* screen incoming connected id */
2180 interface = interface_first;
2183 if (!strcmp(e_connectinfo.interface, interface->name))
2187 interface = interface->next;
2190 screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2192 /* screen connected name */
2194 SCPY(e_connectinfo.name, e_ext.name);
2196 /* add internal id to colp */
2197 SCPY(e_connectinfo.extension, e_ext.number);
2199 /* we store the connected port number */
2200 SCPY(e_extension_interface, e_connectinfo.interface);
2202 /* for internal and am calls, we get the extension's id */
2203 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2205 SCPY(e_connectinfo.id, e_ext.callerid);
2206 SCPY(e_connectinfo.extension, e_ext.number);
2207 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2208 e_connectinfo.ntype = e_ext.callerid_type;
2209 e_connectinfo.present = e_ext.callerid_present;
2211 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2213 e_connectinfo.itype = INFO_ITYPE_VBOX;
2214 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2217 new_state(EPOINT_STATE_CONNECT);
2219 /* set volume of rx and tx */
2220 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2222 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2223 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2224 message->param.mISDNsignal.rxvol = e_ext.txvol;
2225 message->param.mISDNsignal.txvol = e_ext.rxvol;
2226 message_put(message);
2229 e_cfnr_call = e_cfnr_release = 0;
2230 if (e_ext.number[0])
2231 e_dtmf = 1; /* allow dtmf */
2234 /* other calls with no caller id (or not available for the extension) and force colp */
2235 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2237 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2238 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2240 port = find_port_id(portlist->port_id);
2243 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype));
2244 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2249 /* send connect to join */
2250 if (ea_endpoint->ep_join_id)
2252 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2253 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2254 message_put(message);
2256 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2257 message->param.audiopath = CHANNEL_STATE_CONNECT;
2258 message_put(message);
2259 } else if (!e_adminid)
2262 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2263 SCPY(e_ext.number, e_cbcaller);
2264 new_state(EPOINT_STATE_IN_OVERLAP);
2265 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2267 /* get extension's info about terminal */
2268 if (!read_extension(&e_ext, e_ext.number))
2270 /* extension doesn't exist */
2271 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2272 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2273 new_state(EPOINT_STATE_OUT_DISCONNECT);
2274 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2278 /* put prefix in front of e_cbdialing */
2279 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2280 SCPY(e_dialinginfo.id, buffer);
2281 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2282 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2284 /* use caller id (or if exist: id_next_call) for this call */
2285 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2286 SCPY(e_callerinfo.extension, e_ext.number);
2287 if (e_ext.id_next_call_present >= 0)
2289 SCPY(e_callerinfo.id, e_ext.id_next_call);
2290 e_callerinfo.present = e_ext.id_next_call_present;
2291 e_callerinfo.ntype = e_ext.id_next_call_type;
2292 e_ext.id_next_call_present = -1;
2293 /* extension is written */
2294 write_extension(&e_ext, e_ext.number);
2297 SCPY(e_callerinfo.id, e_ext.callerid);
2298 e_callerinfo.present = e_ext.callerid_present;
2299 e_callerinfo.ntype = e_ext.callerid_type;
2302 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2305 /* check if caller id is NOT authenticated */
2306 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2308 /* make call state to enter password */
2309 new_state(EPOINT_STATE_IN_OVERLAP);
2310 e_action = &action_password_write;
2311 e_match_timeout = 0;
2312 e_match_to_action = NULL;
2313 e_dialinginfo.id[0] = '\0';
2314 e_extdialing = strchr(e_dialinginfo.id, '\0');
2315 e_password_timeout = now+20;
2319 /* incoming call (callback) */
2320 e_ruleset = ruleset_main;
2322 e_rule = e_ruleset->rule_first;
2324 e_extdialing = e_dialinginfo.id;
2325 if (e_dialinginfo.id[0])
2327 set_tone(portlist, "dialing");
2331 set_tone(portlist, "dialpbx");
2334 } else /* testcall */
2336 set_tone(portlist, "hold");
2339 /* start recording if enabled, not when answering machine answers */
2340 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))
2342 /* check if we are a terminal */
2343 if (e_ext.number[0] == '\0')
2344 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2347 port = find_port_id(portlist->port_id);
2349 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2354 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2355 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2357 struct message *message;
2359 unsigned long port_id = portlist->port_id;
2363 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2365 /* signal to call tool */
2366 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2368 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2369 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2371 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2376 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);
2377 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2378 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2380 /* check if we have more than one portlist relation and we just ignore the disconnect */
2381 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2383 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2384 portlist = ea_endpoint->ep_portlist;
2387 if (portlist->port_id == port_id)
2389 portlist = portlist->next;
2392 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2393 if (message_type != MESSAGE_RELEASE)
2395 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2396 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2397 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2398 message_put(message);
2399 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2401 ea_endpoint->free_portlist(portlist);
2402 return; /* one relation removed */
2404 if (e_state == EPOINT_STATE_CONNECT)
2406 /* use cause from port after connect */
2407 cause = param->disconnectinfo.cause;
2408 location = param->disconnectinfo.location;
2411 /* use multipoint cause if no connect yet */
2412 if (e_multipoint_cause)
2414 cause = e_multipoint_cause;
2415 location = e_multipoint_location;
2418 cause = CAUSE_NOUSER;
2419 location = LOCATION_PRIVATE_LOCAL;
2423 e_cfnr_call = e_cfnr_release = 0;
2425 /* process hangup */
2426 process_hangup(e_join_cause, e_join_location);
2427 e_multipoint_cause = 0;
2428 e_multipoint_location = 0;
2430 if (message_type == MESSAGE_DISCONNECT)
2432 /* tone to disconnected end */
2433 SPRINT(buffer, "cause_%02x", cause);
2434 if (ea_endpoint->ep_portlist)
2435 set_tone(ea_endpoint->ep_portlist, buffer);
2437 new_state(EPOINT_STATE_IN_DISCONNECT);
2440 if (ea_endpoint->ep_join_id)
2442 int haspatterns = 0;
2443 /* check if pattern is available */
2444 if (ea_endpoint->ep_portlist)
2445 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2446 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
2447 && message_type != MESSAGE_RELEASE) // if we release, we are done
2451 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2452 /* indicate patterns */
2453 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2454 message_put(message);
2455 /* connect audio, if not already */
2456 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2457 message->param.audiopath = CHANNEL_STATE_CONNECT;
2458 message_put(message);
2459 /* send disconnect */
2460 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2461 memcpy(&message->param, param, sizeof(union parameter));
2462 message_put(message);
2463 /* disable encryption if disconnected */
2464 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2466 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2470 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2473 if (message_type == MESSAGE_RELEASE)
2474 ea_endpoint->free_portlist(portlist);
2475 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2476 return; /* must exit here */
2479 /* port MESSAGE_TIMEOUT */
2480 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2484 trace_header("TIMEOUT", DIRECTION_IN);
2485 message_type = MESSAGE_DISCONNECT;
2486 switch (param->state)
2488 case PORT_STATE_OUT_SETUP:
2489 case PORT_STATE_OUT_OVERLAP:
2490 add_trace("state", NULL, "outgoing setup/dialing");
2492 /* no user responding */
2493 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2494 return; /* must exit here */
2496 case PORT_STATE_IN_SETUP:
2497 case PORT_STATE_IN_OVERLAP:
2498 add_trace("state", NULL, "incoming setup/dialing");
2499 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2500 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2503 case PORT_STATE_OUT_PROCEEDING:
2504 add_trace("state", NULL, "outgoing proceeding");
2506 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2507 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2508 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2509 return; /* must exit here */
2511 case PORT_STATE_IN_PROCEEDING:
2512 add_trace("state", NULL, "incoming proceeding");
2513 param->disconnectinfo.cause = CAUSE_NOUSER;
2514 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2517 case PORT_STATE_OUT_ALERTING:
2518 add_trace("state", NULL, "outgoing alerting");
2520 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2521 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2522 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2523 return; /* must exit here */
2525 case PORT_STATE_CONNECT:
2526 add_trace("state", NULL, "connect");
2528 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2529 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2530 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2531 return; /* must exit here */
2533 case PORT_STATE_IN_ALERTING:
2534 add_trace("state", NULL, "incoming alerting");
2535 param->disconnectinfo.cause = CAUSE_NOANSWER;
2536 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2539 case PORT_STATE_IN_DISCONNECT:
2540 case PORT_STATE_OUT_DISCONNECT:
2541 add_trace("state", NULL, "disconnect");
2543 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2544 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2545 return; /* must exit here */
2548 param->disconnectinfo.cause = 31; /* normal unspecified */
2549 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2552 /* release call, disconnect isdn */
2554 new_state(EPOINT_STATE_OUT_DISCONNECT);
2555 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2556 SCPY(e_tone, cause);
2559 set_tone(portlist, cause);
2560 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2561 portlist = portlist->next;
2563 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2566 /* port MESSAGE_NOTIFY */
2567 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2569 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2571 struct message *message;
2575 /* signal to call tool */
2576 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2577 if (param->notifyinfo.notify)
2579 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2582 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2583 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2585 case INFO_NOTIFY_REMOTE_HOLD:
2586 case INFO_NOTIFY_USER_SUSPENDED:
2587 /* tell call about it */
2588 if (ea_endpoint->ep_join_id)
2590 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2591 message->param.audiopath = CHANNEL_STATE_HOLD;
2592 message_put(message);
2596 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2597 case INFO_NOTIFY_USER_RESUMED:
2598 /* set volume of rx and tx */
2599 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2600 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2603 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2604 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2605 message->param.mISDNsignal.rxvol = e_ext.txvol;
2606 message->param.mISDNsignal.txvol = e_ext.rxvol;
2607 message_put(message);
2609 /* set current tone */
2611 set_tone(portlist, e_tone);
2612 /* tell call about it */
2613 if (ea_endpoint->ep_join_id)
2615 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2616 message->param.audiopath = CHANNEL_STATE_CONNECT;
2617 message_put(message);
2622 /* get name of notify */
2623 switch(param->notifyinfo.notify)
2629 logtext = "USER_SUSPENDED";
2632 logtext = "BEARER_SERVICE_CHANGED";
2635 logtext = "USER_RESUMED";
2638 logtext = "CONFERENCE_ESTABLISHED";
2641 logtext = "CONFERENCE_DISCONNECTED";
2644 logtext = "OTHER_PARTY_ADDED";
2647 logtext = "ISOLATED";
2650 logtext = "REATTACHED";
2653 logtext = "OTHER_PARTY_ISOLATED";
2656 logtext = "OTHER_PARTY_REATTACHED";
2659 logtext = "OTHER_PARTY_SPLIT";
2662 logtext = "OTHER_PARTY_DISCONNECTED";
2665 logtext = "CONFERENCE_FLOATING";
2668 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2671 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2674 logtext = "CALL_IS_A_WAITING_CALL";
2677 logtext = "DIVERSION_ACTIVATED";
2680 logtext = "RESERVED_CT_1";
2683 logtext = "RESERVED_CT_2";
2686 logtext = "REVERSE_CHARGING";
2689 logtext = "REMOTE_HOLD";
2692 logtext = "REMOTE_RETRIEVAL";
2695 logtext = "CALL_IS_DIVERTING";
2698 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2703 /* notify call if available */
2704 if (ea_endpoint->ep_join_id)
2706 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2707 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2708 message_put(message);
2713 /* port MESSAGE_FACILITY */
2714 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2716 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2718 struct message *message;
2720 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2721 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2722 message_put(message);
2725 /* port MESSAGE_SUSPEND */
2726 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2727 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2729 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2731 /* epoint is now parked */
2732 ea_endpoint->ep_park = 1;
2733 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2734 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2736 /* remove port relation */
2737 ea_endpoint->free_portlist(portlist);
2740 /* port MESSAGE_RESUME */
2741 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2742 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2744 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2746 /* epoint is now resumed */
2747 ea_endpoint->ep_park = 0;
2752 /* port sends message to the endpoint
2754 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2756 struct port_list *portlist;
2757 struct message *message;
2759 portlist = ea_endpoint->ep_portlist;
2762 if (port_id == portlist->port_id)
2764 portlist = portlist->next;
2768 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);
2772 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2773 switch(message_type)
2775 case MESSAGE_DATA: /* data from port */
2776 /* check if there is a call */
2777 if (!ea_endpoint->ep_join_id)
2779 /* continue if only one portlist */
2780 if (ea_endpoint->ep_portlist->next != NULL)
2782 /* forward message */
2783 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2786 case MESSAGE_TONE_EOF: /* tone is end of file */
2787 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2790 if (e_action->index == ACTION_VBOX_PLAY)
2794 if (e_action->index == ACTION_EFI)
2801 case MESSAGE_TONE_COUNTER: /* counter info received */
2802 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);
2804 if (e_action->index == ACTION_VBOX_PLAY)
2806 e_vbox_counter = param->counter.current;
2807 if (param->counter.max >= 0)
2808 e_vbox_counter_max = param->counter.max;
2812 /* PORT sends SETUP message */
2814 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);
2815 if (e_state!=EPOINT_STATE_IDLE)
2817 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2820 port_setup(portlist, message_type, param);
2823 /* PORT sends INFORMATION message */
2824 case MESSAGE_INFORMATION: /* additional digits received */
2825 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);
2826 port_information(portlist, message_type, param);
2829 /* PORT sends FACILITY message */
2830 case MESSAGE_FACILITY:
2831 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2832 port_facility(portlist, message_type, param);
2835 /* PORT sends DTMF message */
2836 case MESSAGE_DTMF: /* dtmf digits received */
2837 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);
2838 port_dtmf(portlist, message_type, param);
2841 /* PORT sends CRYPT message */
2842 case MESSAGE_CRYPT: /* crypt response received */
2843 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2844 port_crypt(portlist, message_type, param);
2847 /* PORT sends MORE message */
2848 case MESSAGE_OVERLAP:
2849 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);
2850 if (e_state != EPOINT_STATE_OUT_SETUP)
2852 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);
2855 port_overlap(portlist, message_type, param);
2858 /* PORT sends PROCEEDING message */
2859 case MESSAGE_PROCEEDING: /* port is proceeding */
2860 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);
2861 if (e_state!=EPOINT_STATE_OUT_SETUP
2862 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2864 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);
2867 port_proceeding(portlist, message_type, param);
2870 /* PORT sends ALERTING message */
2871 case MESSAGE_ALERTING:
2872 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);
2873 if (e_state!=EPOINT_STATE_OUT_SETUP
2874 && e_state!=EPOINT_STATE_OUT_OVERLAP
2875 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2877 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);
2880 port_alerting(portlist, message_type, param);
2883 /* PORT sends CONNECT message */
2884 case MESSAGE_CONNECT:
2885 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);
2886 if (e_state!=EPOINT_STATE_OUT_SETUP
2887 && e_state!=EPOINT_STATE_OUT_OVERLAP
2888 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2889 && e_state!=EPOINT_STATE_OUT_ALERTING)
2891 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2894 port_connect(portlist, message_type, param);
2897 /* PORT sends DISCONNECT message */
2898 case MESSAGE_DISCONNECT: /* port is disconnected */
2899 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);
2900 port_disconnect_release(portlist, message_type, param);
2903 /* PORT sends a RELEASE message */
2904 case MESSAGE_RELEASE: /* port releases */
2905 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);
2906 /* portlist is release at port_disconnect_release, thanx Paul */
2907 port_disconnect_release(portlist, message_type, param);
2910 /* PORT sends a TIMEOUT message */
2911 case MESSAGE_TIMEOUT:
2912 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);
2913 port_timeout(portlist, message_type, param);
2914 break; /* release */
2916 /* PORT sends a NOTIFY message */
2917 case MESSAGE_NOTIFY:
2918 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);
2919 port_notify(portlist, message_type, param);
2922 /* PORT sends a SUSPEND message */
2923 case MESSAGE_SUSPEND:
2924 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);
2925 port_suspend(portlist, message_type, param);
2926 break; /* suspend */
2928 /* PORT sends a RESUME message */
2929 case MESSAGE_RESUME:
2930 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);
2931 port_resume(portlist, message_type, param);
2935 /* port assigns bchannel */
2936 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2937 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);
2938 /* only one port is expected to be connected to bchannel */
2939 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2940 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2946 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);
2949 /* Note: this endpoint may be destroyed, so we MUST return */
2953 /* messages from join
2955 /* join MESSAGE_CRYPT */
2956 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2958 switch(param->crypt.type)
2960 /* message from remote port to "crypt manager" */
2961 case CU_ACTK_REQ: /* activate key-exchange */
2962 case CU_ACTS_REQ: /* activate shared key */
2963 case CU_DACT_REQ: /* deactivate */
2964 case CU_INFO_REQ: /* request last info message */
2965 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2968 /* message from "crypt manager" to user */
2969 case CU_ACTK_CONF: /* key-echange done */
2970 case CU_ACTS_CONF: /* shared key done */
2971 case CU_DACT_CONF: /* deactivated */
2972 case CU_DACT_IND: /* deactivated */
2973 case CU_ERROR_IND: /* receive error message */
2974 case CU_INFO_IND: /* receive info message */
2975 case CU_INFO_CONF: /* receive info message */
2976 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2980 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);
2984 /* join MESSAGE_INFORMATION */
2985 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2987 struct message *message;
2993 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2994 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2995 message_put(message);
2996 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2997 portlist = portlist->next;
3001 /* join MESSAGE_FACILITY */
3002 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
3004 struct message *message;
3006 if (!e_ext.facility)
3013 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
3014 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
3015 message_put(message);
3016 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3017 portlist = portlist->next;
3021 /* join MESSAGE_MORE */
3022 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
3024 struct message *message;
3026 new_state(EPOINT_STATE_IN_OVERLAP);
3029 if (e_join_pattern && e_ext.own_setup)
3031 /* disconnect audio */
3032 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3033 message->param.audiopath = CHANNEL_STATE_HOLD;
3034 message_put(message);
3036 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3038 set_tone(portlist, "dialtone");
3041 if (e_ext.number[0])
3042 set_tone(portlist, "dialpbx");
3044 set_tone(portlist, "dialtone");
3047 /* join MESSAGE_PROCEEDING */
3048 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
3050 struct message *message;
3052 new_state(EPOINT_STATE_IN_PROCEEDING);
3054 /* own proceeding tone */
3057 /* connect / disconnect audio */
3058 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3059 if (e_ext.own_proceeding)
3060 message->param.audiopath = CHANNEL_STATE_HOLD;
3062 message->param.audiopath = CHANNEL_STATE_CONNECT;
3063 message_put(message);
3065 // UCPY(e_join_tone, "proceeding");
3068 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3069 message_put(message);
3070 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3072 set_tone(portlist, "proceeding");
3075 /* join MESSAGE_ALERTING */
3076 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
3078 struct message *message;
3080 new_state(EPOINT_STATE_IN_ALERTING);
3082 /* own alerting tone */
3085 /* connect / disconnect audio */
3086 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3087 if (e_ext.own_alerting)
3088 message->param.audiopath = CHANNEL_STATE_HOLD;
3090 message->param.audiopath = CHANNEL_STATE_CONNECT;
3091 message_put(message);
3095 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
3096 message_put(message);
3097 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3099 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3101 set_tone(portlist, "ringing");
3104 if (e_ext.number[0])
3105 set_tone(portlist, "ringpbx");
3107 set_tone(portlist, "ringing");
3110 /* join MESSAGE_CONNECT */
3111 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
3113 struct message *message;
3114 struct interface *interface;
3116 new_state(EPOINT_STATE_CONNECT);
3117 // UCPY(e_join_tone, "");
3118 if (e_ext.number[0])
3119 e_dtmf = 1; /* allow dtmf */
3121 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
3124 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3125 memcpy(&message->param, param, sizeof(union parameter));
3126 /* screen incoming caller id */
3127 interface = interface_first;
3130 if (!strcmp(e_connectinfo.interface, interface->name))
3134 interface = interface->next;
3137 screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
3138 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(e_connectinfo));
3140 /* screen clip if prefix is required */
3141 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3143 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3144 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
3145 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3148 /* use internal caller id */
3149 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3151 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
3152 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3155 /* handle restricted caller ids */
3156 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);
3157 /* display callerid if desired for extension */
3158 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));
3160 /* use conp, if enabld */
3162 message->param.connectinfo.name[0] = '\0';
3165 message_put(message);
3166 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3168 set_tone(portlist, NULL);
3170 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3171 message->param.audiopath = CHANNEL_STATE_CONNECT;
3172 message_put(message);
3176 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3177 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3180 struct message *message;
3181 struct port_list *portlist = NULL;
3184 /* be sure that we are active */
3186 e_tx_state = NOTIFY_STATE_ACTIVE;
3188 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3189 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3191 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3193 /* set time for power dialing */
3194 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3197 /* set redial tone */
3198 if (ea_endpoint->ep_portlist)
3202 set_tone(ea_endpoint->ep_portlist, "redial");
3203 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);
3204 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3205 if (e_state==EPOINT_STATE_IN_OVERLAP)
3207 new_state(EPOINT_STATE_IN_PROCEEDING);
3208 if (ea_endpoint->ep_portlist)
3210 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3211 message_put(message);
3212 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3214 /* caused the error, that the first knock sound was not there */
3215 /* set_tone(portlist, "proceeding"); */
3217 /* send display of powerdialing */
3218 if (e_ext.display_dialing)
3220 portlist = ea_endpoint->ep_portlist;
3223 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3225 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3227 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3228 message_put(message);
3229 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3230 portlist = portlist->next;
3239 if ((e_state!=EPOINT_STATE_CONNECT
3240 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3241 && e_state!=EPOINT_STATE_IN_OVERLAP
3242 && e_state!=EPOINT_STATE_IN_PROCEEDING
3243 && e_state!=EPOINT_STATE_IN_ALERTING)
3244 || !ea_endpoint->ep_portlist) /* or no port */
3246 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3247 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3248 return; /* must exit here */
3253 e_join_cause = param->disconnectinfo.cause;
3254 e_join_location = param->disconnectinfo.location;
3257 /* on release we need the audio again! */
3258 if (message_type == MESSAGE_RELEASE)
3261 ea_endpoint->ep_join_id = 0;
3263 /* disconnect and select tone */
3264 new_state(EPOINT_STATE_OUT_DISCONNECT);
3265 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3266 /* if own_cause, we must release the join */
3267 if (e_ext.own_cause /* own cause */
3268 || !e_join_pattern) /* no patterns */
3270 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);
3271 if (message_type != MESSAGE_RELEASE)
3272 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3274 } else /* else we enable audio */
3276 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3277 message->param.audiopath = CHANNEL_STATE_CONNECT;
3278 message_put(message);
3280 /* send disconnect message */
3281 SCPY(e_tone, cause);
3282 portlist = ea_endpoint->ep_portlist;
3285 set_tone(portlist, cause);
3286 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3287 portlist = portlist->next;
3291 /* join MESSAGE_SETUP */
3292 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3294 struct message *message;
3295 struct interface *interface;
3297 /* if we already in setup state, we just update the dialing with new digits */
3298 if (e_state == EPOINT_STATE_OUT_SETUP
3299 || e_state == EPOINT_STATE_OUT_OVERLAP)
3301 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3302 /* if digits changed, what we have already dialed */
3303 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3305 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);
3306 /* release all ports */
3307 while((portlist = ea_endpoint->ep_portlist))
3309 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3310 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3311 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3312 message_put(message);
3313 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3314 ea_endpoint->free_portlist(portlist);
3317 /* disconnect audio */
3318 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3319 message->param.audiopath = CHANNEL_STATE_HOLD;
3320 message_put(message);
3322 /* get dialing info */
3323 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3324 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3325 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3326 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3327 new_state(EPOINT_STATE_OUT_OVERLAP);
3330 e_redial = now_d + 1; /* set redial one second in the future */
3333 /* if we have a pending redial, so we just adjust the dialing number */
3336 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);
3337 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3340 if (!ea_endpoint->ep_portlist)
3342 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3344 if (ea_endpoint->ep_portlist->next)
3346 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3348 if (e_state == EPOINT_STATE_OUT_SETUP)
3351 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);
3352 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3356 /* get what we have not dialed yet */
3357 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));
3358 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3359 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3360 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3361 message_put(message);
3362 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3364 /* always store what we have dialed or queued */
3365 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3369 if (e_state != EPOINT_STATE_IDLE)
3371 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3374 /* if an internal extension is dialed, copy that number */
3375 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3376 SCPY(e_ext.number, param->setup.dialinginfo.id);
3377 /* if an internal extension is dialed, get extension's info about caller */
3378 if (e_ext.number[0])
3380 if (!read_extension(&e_ext, e_ext.number))
3382 e_ext.number[0] = '\0';
3383 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3387 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3388 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3389 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3390 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3392 /* screen incoming caller id */
3393 interface = interface_first;
3396 if (!strcmp(e_callerinfo.interface, interface->name))
3400 interface = interface->next;
3403 screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
3405 /* process (voice over) data calls */
3406 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3408 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3409 memset(&e_capainfo, 0, sizeof(e_capainfo));
3410 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3411 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3412 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3415 new_state(EPOINT_STATE_OUT_SETUP);
3416 /* call special setup routine */
3420 /* join MESSAGE_mISDNSIGNAL */
3421 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3423 struct message *message;
3427 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3428 memcpy(&message->param, param, sizeof(union parameter));
3429 message_put(message);
3430 portlist = portlist->next;
3434 /* join MESSAGE_NOTIFY */
3435 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3437 struct message *message;
3440 if (param->notifyinfo.notify)
3442 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3443 // /* if notification was generated locally, we turn hold music on/off */
3444 // if (param->notifyinfo.local)
3445 // 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)
3450 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3452 if (!strcmp(e_tone, "hold")) // don't interrupt other tones
3456 set_tone(portlist, "");
3457 portlist = portlist->next;
3460 portlist = ea_endpoint->ep_portlist;
3465 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3469 set_tone(portlist, "hold");
3470 portlist = portlist->next;
3472 portlist = ea_endpoint->ep_portlist;
3477 /* save new state */
3478 e_tx_state = new_state;
3481 /* notify port(s) about it */
3484 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3485 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3486 /* handle restricted caller ids */
3487 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);
3488 /* display callerid if desired for extension */
3489 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));
3490 message_put(message);
3491 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3492 portlist = portlist->next;
3496 /* JOIN sends messages to the endpoint
3498 void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, union parameter *param)
3500 struct port_list *portlist;
3501 struct message *message;
3505 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3509 portlist = ea_endpoint->ep_portlist;
3511 /* send MESSAGE_DATA to port */
3512 if (message_type == MESSAGE_DATA)
3514 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3516 /* skip if no port relation */
3519 /* skip if more than one port relation */
3522 /* forward audio data to port */
3523 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3528 // 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);
3529 switch(message_type)
3531 /* JOIN SENDS TONE message */
3533 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);
3534 set_tone(portlist, param->tone.name);
3537 /* JOIN SENDS CRYPT message */
3539 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);
3540 join_crypt(portlist, message_type, param);
3543 /* JOIN sends INFORMATION message */
3544 case MESSAGE_INFORMATION:
3545 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);
3546 join_information(portlist, message_type, param);
3549 /* JOIN sends FACILITY message */
3550 case MESSAGE_FACILITY:
3551 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);
3552 join_facility(portlist, message_type, param);
3555 /* JOIN sends OVERLAP message */
3556 case MESSAGE_OVERLAP:
3557 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);
3558 if (e_state!=EPOINT_STATE_IN_SETUP
3559 && e_state!=EPOINT_STATE_IN_OVERLAP)
3561 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3564 join_overlap(portlist, message_type, param);
3567 /* JOIN sends PROCEEDING message */
3568 case MESSAGE_PROCEEDING:
3569 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);
3570 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3572 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3575 join_proceeding(portlist, message_type, param);
3578 /* JOIN sends ALERTING message */
3579 case MESSAGE_ALERTING:
3580 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);
3581 if (e_state!=EPOINT_STATE_IN_OVERLAP
3582 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3584 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3587 join_alerting(portlist, message_type, param);
3590 /* JOIN sends CONNECT message */
3591 case MESSAGE_CONNECT:
3592 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);
3593 if (e_state!=EPOINT_STATE_IN_OVERLAP
3594 && e_state!=EPOINT_STATE_IN_PROCEEDING
3595 && e_state!=EPOINT_STATE_IN_ALERTING)
3597 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3600 join_connect(portlist, message_type, param);
3603 /* JOIN sends DISCONNECT/RELEASE message */
3604 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3605 case MESSAGE_RELEASE: /* JOIN releases */
3606 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);
3607 join_disconnect_release(message_type, param);
3610 /* JOIN sends SETUP message */
3612 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);
3613 join_setup(portlist, message_type, param);
3616 /* JOIN sends special mISDNSIGNAL message */
3617 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3618 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);
3619 join_mISDNsignal(portlist, message_type, param);
3623 /* JOIN requests bchannel */
3624 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3625 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);
3626 /* only one port is expected to be connected to bchannel */
3633 set_tone(portlist, NULL);
3634 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3635 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3639 /* JOIN has pattern available */
3640 case MESSAGE_PATTERN: /* indicating pattern available */
3641 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);
3642 if (!e_join_pattern)
3644 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3649 set_tone(portlist, NULL);
3650 portlist = portlist->next;
3652 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3653 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3654 message->param.audiopath = CHANNEL_STATE_CONNECT;
3655 message_put(message);
3656 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3657 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_REMOTE_AUDIO);
3658 // message->param.audiopath = CHANNEL_STATE_CONNECT;
3659 // message_put(message);
3660 // patterns are available, remote already connected audio
3664 /* JOIN has no pattern available */
3665 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3666 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);
3669 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3671 /* disconnect our audio tx and rx */
3672 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3673 message->param.audiopath = CHANNEL_STATE_HOLD;
3674 message_put(message);
3679 /* JOIN (dunno at the moment) */
3680 case MESSAGE_REMOTE_AUDIO:
3681 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);
3682 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3683 message->param.audiopath = param->channel;
3684 message_put(message);
3688 /* JOIN sends a notify message */
3689 case MESSAGE_NOTIFY:
3690 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);
3691 join_notify(portlist, message_type, param);
3695 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);
3700 /* pick_join will connect the first incoming call found. the endpoint
3701 * will receivce a MESSAGE_CONNECT.
3703 int match_list(char *list, char *item)
3705 char *end, *next = NULL;
3707 /* no list make matching */
3713 /* eliminate white spaces */
3714 while (*list <= ' ')
3721 /* if end of list is reached, we return */
3722 if (list[0] == '\0')
3724 /* if we have more than one entry (left) */
3725 if ((end = strchr(list, ',')))
3728 next = end = strchr(list, '\0');
3729 while (*(end-1) <= ' ')
3731 /* if string part matches item */
3732 if (!strncmp(list, item, end-list))
3738 void EndpointAppPBX::pick_join(char *extensions)
3740 struct message *message;
3741 struct port_list *portlist;
3743 class EndpointAppPBX *eapp, *found;
3745 class JoinPBX *joinpbx;
3746 struct join_relation *relation;
3749 /* find an endpoint that is ringing internally or vbox with higher priority */
3752 eapp = apppbx_first;
3755 if (eapp!=this && ea_endpoint->ep_portlist)
3757 portlist = eapp->ea_endpoint->ep_portlist;
3760 if ((port = find_port_id(portlist->port_id)))
3762 if (port->p_type == PORT_TYPE_VBOX_OUT)
3764 if (match_list(extensions, eapp->e_ext.number))
3771 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3772 && port->p_state==PORT_STATE_OUT_ALERTING)
3773 if (match_list(extensions, eapp->e_ext.number))
3778 portlist = portlist->next;
3786 /* if no endpoint found */
3789 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);
3791 set_tone(ea_endpoint->ep_portlist, "cause_10");
3792 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3793 new_state(EPOINT_STATE_OUT_DISCONNECT);
3798 if (ea_endpoint->ep_join_id)
3800 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3803 if (!eapp->ea_endpoint->ep_join_id)
3805 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3808 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3811 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3814 if (join->j_type != JOIN_TYPE_PBX)
3816 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3819 joinpbx = (class JoinPBX *)join;
3820 relation = joinpbx->j_relation;
3823 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3826 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3828 relation = relation->next;
3831 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3836 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3838 if (options.deb & DEBUG_EPOINT)
3840 class Join *debug_c = join_first;
3841 class Endpoint *debug_e = epoint_first;
3842 class Port *debug_p = port_first;
3844 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3846 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3849 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3850 debug_c = debug_c->next;
3852 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3855 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3856 debug_e = debug_e->next;
3858 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3861 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3862 debug_p = debug_p->next;
3867 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3868 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3869 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3871 /* connnecting our endpoint */
3872 new_state(EPOINT_STATE_CONNECT);
3874 set_tone(ea_endpoint->ep_portlist, NULL);
3876 /* now we send a release to the ringing endpoint */
3877 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3878 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3879 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3880 message_put(message);
3882 /* we send a connect to the join with our caller id */
3883 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3884 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3885 message->param.connectinfo.present = e_callerinfo.present;
3886 message->param.connectinfo.screen = e_callerinfo.screen;
3887 message->param.connectinfo.itype = e_callerinfo.itype;
3888 message->param.connectinfo.ntype = e_callerinfo.ntype;
3889 message_put(message);
3891 /* we send a connect to our port with the remote callerid */
3892 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3893 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3894 message->param.connectinfo.present = eapp->e_callerinfo.present;
3895 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3896 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3897 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3898 /* handle restricted caller ids */
3899 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);
3900 /* display callerid if desired for extension */
3901 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));
3902 message_put(message);
3904 /* we send a connect to the audio path (not for vbox) */
3905 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3906 message->param.audiopath = CHANNEL_STATE_CONNECT;
3907 message_put(message);
3909 /* beeing paranoid, we make call update */
3910 joinpbx->j_updatebridge = 1;
3912 if (options.deb & DEBUG_EPOINT)
3914 class Join *debug_c = join_first;
3915 class Endpoint *debug_e = epoint_first;
3916 class Port *debug_p = port_first;
3918 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3920 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3923 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3924 debug_c = debug_c->next;
3926 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3929 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3930 debug_e = debug_e->next;
3932 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3935 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3936 debug_p = debug_p->next;
3942 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3944 void EndpointAppPBX::join_join(void)
3946 struct message *message;
3947 struct join_relation *our_relation, *other_relation;
3948 struct join_relation **our_relation_pointer, **other_relation_pointer;
3949 class Join *our_join, *other_join;
3950 class JoinPBX *our_joinpbx, *other_joinpbx;
3951 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3952 class Port *our_port, *other_port;
3953 class Pdss1 *our_pdss1, *other_pdss1;
3955 /* are we a candidate to join a join */
3956 our_join = find_join_id(ea_endpoint->ep_join_id);
3959 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3962 if (our_join->j_type != JOIN_TYPE_PBX)
3964 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3967 our_joinpbx = (class JoinPBX *)our_join;
3968 if (!ea_endpoint->ep_portlist)
3970 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3973 if (!e_ext.number[0])
3975 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3978 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3981 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3984 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3986 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3989 our_pdss1 = (class Pdss1 *)our_port;
3991 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3992 other_eapp = apppbx_first;
3995 if (other_eapp == this)
3997 other_eapp = other_eapp->next;
4000 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);
4001 if (other_eapp->e_ext.number[0] /* has terminal */
4002 && other_eapp->ea_endpoint->ep_portlist /* has port */
4003 && other_eapp->ea_endpoint->ep_join_id) /* has join */
4005 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
4006 if (other_port) /* port still exists */
4008 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
4009 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
4011 other_pdss1 = (class Pdss1 *)other_port;
4012 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);
4013 if (other_pdss1->p_m_hold /* port is on hold */
4014 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
4015 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
4019 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
4023 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
4026 other_eapp = other_eapp->next;
4030 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
4033 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
4035 /* if we have the same join */
4036 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
4038 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
4041 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
4044 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
4047 if (other_join->j_type != JOIN_TYPE_PBX)
4049 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
4052 other_joinpbx = (class JoinPBX *)other_join;
4053 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
4055 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
4059 /* remove relation to endpoint for join on hold */
4060 other_relation = other_joinpbx->j_relation;
4061 other_relation_pointer = &other_joinpbx->j_relation;
4062 while(other_relation)
4064 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
4066 /* detach other endpoint on hold */
4067 *other_relation_pointer = other_relation->next;
4068 FREE(other_relation, sizeof(struct join_relation));
4070 other_relation = *other_relation_pointer;
4071 other_eapp->ea_endpoint->ep_join_id = NULL;
4075 /* change join/hold pointer of endpoint to the new join */
4076 temp_epoint = find_epoint_id(other_relation->epoint_id);
4079 if (temp_epoint->ep_join_id == other_join->j_serial)
4080 temp_epoint->ep_join_id = our_join->j_serial;
4083 other_relation_pointer = &other_relation->next;
4084 other_relation = other_relation->next;
4086 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
4088 /* join call relations */
4089 our_relation = our_joinpbx->j_relation;
4090 our_relation_pointer = &our_joinpbx->j_relation;
4093 our_relation_pointer = &our_relation->next;
4094 our_relation = our_relation->next;
4096 *our_relation_pointer = other_joinpbx->j_relation;
4097 other_joinpbx->j_relation = NULL;
4098 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
4100 /* release endpoint on hold */
4101 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
4102 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
4103 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
4104 message_put(message);
4106 /* if we are not a partyline, we get partyline state from other join */
4107 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
4109 /* remove empty join */
4111 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
4113 /* mixer must update */
4114 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
4116 /* we send a retrieve to that endpoint */
4117 // mixer will update the hold-state of the join and send it to the endpoints is changes
4121 /* check if we have an external call
4122 * this is used to check for encryption ability
4124 int EndpointAppPBX::check_external(char **errstr, class Port **port)
4126 struct join_relation *relation;
4128 class JoinPBX *joinpbx;
4129 class Endpoint *epoint;
4131 /* some paranoia check */
4132 if (!ea_endpoint->ep_portlist)
4134 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4135 *errstr = "No Call";
4138 if (!e_ext.number[0])
4140 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4141 *errstr = "No Call";
4145 /* check if we have a join with 2 parties */
4146 join = find_join_id(ea_endpoint->ep_join_id);
4149 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
4150 *errstr = "No Call";
4153 if (join->j_type != JOIN_TYPE_PBX)
4155 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
4156 *errstr = "No PBX Call";
4159 joinpbx = (class JoinPBX *)join;
4160 relation = joinpbx->j_relation;
4163 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
4164 *errstr = "No Call";
4167 if (!relation->next)
4169 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
4170 *errstr = "No Call";
4173 if (relation->next->next)
4175 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4176 *errstr = "Err: Conference";
4179 if (relation->epoint_id == ea_endpoint->ep_serial)
4181 relation = relation->next;
4182 if (relation->epoint_id == ea_endpoint->ep_serial)
4184 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4185 *errstr = "Software Error";
4190 /* check remote port for external call */
4191 epoint = find_epoint_id(relation->epoint_id);
4194 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4195 *errstr = "No Call";
4198 if (!epoint->ep_portlist)
4200 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4201 *errstr = "No Call";
4204 *port = find_port_id(epoint->ep_portlist->port_id);
4207 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4208 *errstr = "No Call";
4211 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4213 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4214 *errstr = "No Ext Call";
4217 if ((*port)->p_state != PORT_STATE_CONNECT)
4219 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4220 *errstr = "No Ext Connect";
4226 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned long port_id, int dir)
4228 char *logtext = "unknown";
4231 switch(message_type)
4234 trace_header("SETUP", dir);
4235 if (dir == DIRECTION_OUT)
4236 add_trace("to", NULL, "CH(%lu)", port_id);
4237 if (dir == DIRECTION_IN)
4238 add_trace("from", NULL, "CH(%lu)", port_id);
4239 if (param->setup.callerinfo.extension[0])
4240 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4241 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype));
4242 switch(param->setup.callerinfo.present)
4244 case INFO_PRESENT_RESTRICTED:
4245 add_trace("caller id", "present", "restricted");
4247 case INFO_PRESENT_ALLOWED:
4248 add_trace("caller id", "present", "allowed");
4251 add_trace("caller id", "present", "not available");
4253 if (param->setup.redirinfo.id[0])
4255 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype));
4256 switch(param->setup.redirinfo.present)
4258 case INFO_PRESENT_RESTRICTED:
4259 add_trace("redir'ing", "present", "restricted");
4261 case INFO_PRESENT_ALLOWED:
4262 add_trace("redir'ing", "present", "allowed");
4265 add_trace("redir'ing", "present", "not available");
4268 if (param->setup.dialinginfo.id[0])
4269 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4273 case MESSAGE_OVERLAP:
4274 trace_header("SETUP ACKNOWLEDGE", 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_PROCEEDING:
4283 trace_header("PROCEEDING", 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_ALERTING:
4292 trace_header("ALERTING", 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);
4300 case MESSAGE_CONNECT:
4301 trace_header("CONNECT", dir);
4302 if (dir == DIRECTION_OUT)
4303 add_trace("to", NULL, "CH(%lu)", port_id);
4304 if (dir == DIRECTION_IN)
4305 add_trace("from", NULL, "CH(%lu)", port_id);
4306 if (param->connectinfo.extension[0])
4307 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4308 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype));
4309 switch(param->connectinfo.present)
4311 case INFO_PRESENT_RESTRICTED:
4312 add_trace("connect id", "present", "restricted");
4314 case INFO_PRESENT_ALLOWED:
4315 add_trace("connect id", "present", "allowed");
4318 add_trace("connect id", "present", "not available");
4323 case MESSAGE_DISCONNECT:
4324 case MESSAGE_RELEASE:
4325 if (message_type == MESSAGE_DISCONNECT)
4326 trace_header("DISCONNECT", dir);
4328 trace_header("RELEASE", dir);
4329 if (dir == DIRECTION_OUT)
4330 add_trace("to", NULL, "CH(%lu)", port_id);
4331 if (dir == DIRECTION_IN)
4332 add_trace("from", NULL, "CH(%lu)", port_id);
4333 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4334 switch(param->disconnectinfo.location)
4337 add_trace("cause", "location", "0-User");
4339 case LOCATION_PRIVATE_LOCAL:
4340 add_trace("cause", "location", "1-Local-PBX");
4342 case LOCATION_PUBLIC_LOCAL:
4343 add_trace("cause", "location", "2-Local-Exchange");
4345 case LOCATION_TRANSIT:
4346 add_trace("cause", "location", "3-Transit");
4348 case LOCATION_PUBLIC_REMOTE:
4349 add_trace("cause", "location", "4-Remote-PBX");
4351 case LOCATION_PRIVATE_REMOTE:
4352 add_trace("cause", "location", "5-Remote-Exchange");
4354 case LOCATION_INTERNATIONAL:
4355 add_trace("cause", "location", "7-International-Exchange");
4357 case LOCATION_BEYOND:
4358 add_trace("cause", "location", "10-Beyond-Interworking");
4361 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4366 case MESSAGE_NOTIFY:
4367 switch(param->notifyinfo.notify)
4373 logtext = "USER_SUSPENDED";
4376 logtext = "BEARER_SERVICE_CHANGED";
4379 logtext = "USER_RESUMED";
4382 logtext = "CONFERENCE_ESTABLISHED";
4385 logtext = "CONFERENCE_DISCONNECTED";
4388 logtext = "OTHER_PARTY_ADDED";
4391 logtext = "ISOLATED";
4394 logtext = "REATTACHED";
4397 logtext = "OTHER_PARTY_ISOLATED";
4400 logtext = "OTHER_PARTY_REATTACHED";
4403 logtext = "OTHER_PARTY_SPLIT";
4406 logtext = "OTHER_PARTY_DISCONNECTED";
4409 logtext = "CONFERENCE_FLOATING";
4412 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4415 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4418 logtext = "CALL_IS_A_WAITING_CALL";
4421 logtext = "DIVERSION_ACTIVATED";
4424 logtext = "RESERVED_CT_1";
4427 logtext = "RESERVED_CT_2";
4430 logtext = "REVERSE_CHARGING";
4433 logtext = "REMOTE_HOLD";
4436 logtext = "REMOTE_RETRIEVAL";
4439 logtext = "CALL_IS_DIVERTING";
4442 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4446 trace_header("NOTIFY", dir);
4447 if (dir == DIRECTION_OUT)
4448 add_trace("to", NULL, "CH(%lu)", port_id);
4449 if (dir == DIRECTION_IN)
4450 add_trace("from", NULL, "CH(%lu)", port_id);
4451 if (param->notifyinfo.notify)
4452 add_trace("indicator", NULL, "%s", logtext);
4453 if (param->notifyinfo.id[0])
4455 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype));
4456 switch(param->notifyinfo.present)
4458 case INFO_PRESENT_RESTRICTED:
4459 add_trace("redir'on", "present", "restricted");
4461 case INFO_PRESENT_ALLOWED:
4462 add_trace("redir'on", "present", "allowed");
4465 add_trace("redir'on", "present", "not available");
4468 if (param->notifyinfo.display[0])
4469 add_trace("display", NULL, "%s", param->notifyinfo.display);
4473 case MESSAGE_INFORMATION:
4474 trace_header("INFORMATION", dir);
4475 if (dir == DIRECTION_OUT)
4476 add_trace("to", NULL, "CH(%lu)", port_id);
4477 if (dir == DIRECTION_IN)
4478 add_trace("from", NULL, "CH(%lu)", port_id);
4479 add_trace("dialing", NULL, "%s", param->information.id);
4483 case MESSAGE_FACILITY:
4484 trace_header("FACILITY", 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);
4493 trace_header("TONE", dir);
4494 if (dir == DIRECTION_OUT)
4495 add_trace("to", NULL, "CH(%lu)", port_id);
4496 if (dir == DIRECTION_IN)
4497 add_trace("from", NULL, "CH(%lu)", port_id);
4498 if (param->tone.name[0])
4500 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4501 add_trace("name", NULL, "%s", param->tone.name);
4503 add_trace("off", NULL, NULL);
4507 case MESSAGE_SUSPEND:
4508 case MESSAGE_RESUME:
4509 if (message_type == MESSAGE_SUSPEND)
4510 trace_header("SUSPEND", dir);
4512 trace_header("RESUME", dir);
4513 if (dir == DIRECTION_OUT)
4514 add_trace("to", NULL, "CH(%lu)", port_id);
4515 if (dir == DIRECTION_IN)
4516 add_trace("from", NULL, "CH(%lu)", port_id);
4517 if (param->parkinfo.len)
4518 add_trace("length", NULL, "%d", param->parkinfo.len);
4523 case MESSAGE_BCHANNEL:
4524 trace_header("BCHANNEL", dir);
4525 switch(param->bchannel.type)
4527 case BCHANNEL_REQUEST:
4528 add_trace("type", NULL, "request");
4530 case BCHANNEL_ASSIGN:
4531 add_trace("type", NULL, "assign");
4533 case BCHANNEL_ASSIGN_ACK:
4534 add_trace("type", NULL, "assign_ack");
4536 case BCHANNEL_REMOVE:
4537 add_trace("type", NULL, "remove");
4539 case BCHANNEL_REMOVE_ACK:
4540 add_trace("type", NULL, "remove_ack");
4543 if (param->bchannel.addr)
4544 add_trace("address", NULL, "%x", param->bchannel.addr);
4550 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4554 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4556 struct message *message;
4560 if (!portlist->port_id)
4563 if (!e_connectedmode)
4565 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4566 message->param.disconnectinfo.cause = cause;
4567 message->param.disconnectinfo.location = location;
4569 SCPY(message->param.disconnectinfo.display, display);
4571 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4574 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4576 SCPY(message->param.notifyinfo.display, display);
4578 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4580 message_put(message);
4581 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);