From 559ff64e3062b70f27ddceba825f40642a6c5725 Mon Sep 17 00:00:00 2001 From: Super User Date: Wed, 9 May 2007 07:39:20 +0200 Subject: [PATCH] backup work --- admin.h | 8 +++ admin_server.c | 6 ++ apppbx.cpp | 91 +++++++++++++++++----------- dss1.cpp | 188 ++++++++++++++++++++++++++++++++++++++------------------- endpoint.cpp | 14 +++-- endpoint.h | 1 + interface.c | 58 +++++++++++++++++- interface.h | 1 - mISDN.cpp | 16 +++-- mISDN.h | 2 + message.h | 11 ++-- options.c | 8 --- options.h | 1 - todo.txt | 19 ++++-- 14 files changed, 293 insertions(+), 131 deletions(-) diff --git a/admin.h b/admin.h index 3e7b7ed..da3b069 100644 --- a/admin.h +++ b/admin.h @@ -36,6 +36,7 @@ enum { /* messages */ ADMIN_CALL_DISCONNECT, ADMIN_CALL_RELEASE, ADMIN_CALL_NOTIFY, + ADMIN_MESSAGE, }; struct admin_response_cmd { @@ -118,6 +119,12 @@ struct admin_call { }; struct admin_message { + int type; /* type of message */ + unsigned long ref; /* reference to individual endpoints */ + union parameter param; /* parameter union */ +}; + +struct admin_message { int message; /* type of admin message */ union u { struct admin_response_cmd x; @@ -127,6 +134,7 @@ struct admin_message { struct admin_response_epoint e; struct admin_response_call c; struct admin_call call; + struct admin_message message; } u; }; diff --git a/admin_server.c b/admin_server.c index 80f2875..c17620b 100644 --- a/admin_server.c +++ b/admin_server.c @@ -912,6 +912,12 @@ int admin_handle(void) if (admin_state(&admin->response) < 0) { PERROR("Failed to create state response for socket %d.\n", admin->sock); + goto response_error; + } + case ADMIN_REQUEST_MESSAGE: + if (admin_message(&admin->response) < 0) + { + PERROR("Failed to create message response for socket %d.\n", admin->sock); response_error: *adminp = admin->next; free_connection(admin); diff --git a/apppbx.cpp b/apppbx.cpp index 1d07900..c00ab69 100644 --- a/apppbx.cpp +++ b/apppbx.cpp @@ -279,8 +279,10 @@ void apply_callerid_restriction(int anon_ignore, int port_type, char *id, int *n if (*present != INFO_PRESENT_RESTRICTED) return; - /* external ports receive no restricted caller id */ - if (port_type==PORT_TYPE_DSS1_TE_IN || port_type==PORT_TYPE_DSS1_TE_OUT) + /* only extensions are restricted */ + if (!intern) + return; + if (!intern[0]) return; /* if we enabled anonymouse ignore */ @@ -631,7 +633,7 @@ static struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel) /* see if port is available */ if (!ifport->mISDNport) { - printlog("%3d port#%d position %d is not available, skipping.\n", ea_endpoint->ep_serial, ifport_start->portnum, index); + printlog("%3d port#%d position %d is not available, skipping.\n", ea_endpoint->ep_serial, ifport->portnum, index); goto portbusy; } mISDNport = ifport->mISDNport; @@ -641,14 +643,14 @@ static struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel) /* see if port is administratively blocked */ if (ifport->block) { - printlog("%3d port#%d position %d is administratively blocked, skipping.\n", ea_endpoint->ep_serial, ifport_start->portnum, index); + printlog("%3d port#%d position %d is administratively blocked, skipping.\n", ea_endpoint->ep_serial, ifport->portnum, index); goto portbusy; } /* see if link is up */ if (mISDNport->ptp && !mISDNport->l2link) { - printlog("%3d port#%d position %d is ptp but layer 2 is down.\n", ea_endpoint->ep_serial, ifport_start->portnum, index); + printlog("%3d port#%d position %d is ptp but layer 2 is down.\n", ea_endpoint->ep_serial, ifport->portnum, index); PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is PTP with L2 down\n", ea_endpoint->ep_serial); goto portbusy; } @@ -670,7 +672,7 @@ static struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel) if (mISDNport->b_port[i] == NULL) { *channel = i+1+(i>=15); - printlog("%3d port#%d position %d selecting free channel %d\n", ea_endpoint->ep_serial, ifport_start->portnum, index, *channel); + printlog("%3d port#%d position %d selecting free channel %d\n", ea_endpoint->ep_serial, ifport->portnum, index, *channel); break; } i++; @@ -682,12 +684,12 @@ static struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel) { break; /* all channel in use or reserverd */ } - printlog("%3d port#%d position %d using with 'any channel'\n", ea_endpoint->ep_serial, ifport_start->portnum, index); + printlog("%3d port#%d position %d using with 'any channel'\n", ea_endpoint->ep_serial, ifport->portnum, index); *channel = SEL_CHANNEL_ANY; break; case CHANNEL_NO: /* call waiting */ - printlog("%3d port#%d position %d using with 'no channel'\n", ea_endpoint->ep_serial, ifport_start->portnum, index); + printlog("%3d port#%d position %d using with 'no channel'\n", ea_endpoint->ep_serial, ifport->portnum, index); *channel = SEL_CHANNEL_NO; break; @@ -700,14 +702,13 @@ static struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel) if (mISDNport->b_port[i] == NULL) { *channel = selchannel->channel; - printlog("%3d port#%d position %d selecting given channel %d\n", ea_endpoint->ep_serial, ifport_start->portnum, index, *channel); + printlog("%3d port#%d position %d selecting given channel %d\n", ea_endpoint->ep_serial, ifport->portnum, index, *channel); break; } break; } if (*channel) break; /* found channel */ - printlog("%3d port#%d position %d skipping, because no channel found.\n", ea_endpoint->ep_serial, ifport_start->portnum, index); selchannel = selchannel->next; } @@ -726,6 +727,8 @@ static struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel) return(mISDNport); } + printlog("%3d port#%d position %d skipping, because no channel found.\n", ea_endpoint->ep_serial, ifport->portnum, index); + portbusy: /* go next port, until all ports are checked */ index++; @@ -921,10 +924,10 @@ void EndpointAppPBX::out_setup(void) PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name); memset(&dialinginfo, 0, sizeof(dialinginfo)); SCPY(dialinginfo.number, e_dialinginfo.number); - dialinginfo.itype = INFO_ITYPE_INTERN; + dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION; dialinginfo.ntype = e_dialinginfo.ntype; /* create port_list relation */ - portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type); + portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->is_earlyb); if (!portlist) { PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial); @@ -995,6 +998,7 @@ void EndpointAppPBX::out_setup(void) while(*p) { /* only if vbox should be dialed, and terminal is given */ + earlyb = 0; if (!strcmp(p, "vbox") && e_terminal[0]) { /* go to the end of p */ @@ -1069,6 +1073,7 @@ void EndpointAppPBX::out_setup(void) /* creating EXTERNAL port*/ SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum); port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings); + earlyb = mISDNport->is_earlyb; } else { port = NULL; @@ -1086,7 +1091,7 @@ void EndpointAppPBX::out_setup(void) SCPY(dialinginfo.number, cfp); dialinginfo.itype = INFO_ITYPE_EXTERN; dialinginfo.ntype = e_dialinginfo.ntype; - portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type); + portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb); if (!portlist) { PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial); @@ -1149,7 +1154,7 @@ void EndpointAppPBX::out_setup(void) SCPY(dialinginfo.number, e_dialinginfo.number); dialinginfo.itype = INFO_ITYPE_H323; dialinginfo.ntype = e_dialinginfo.ntype; - portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type); + portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, 0); if (!portlist) { PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial); @@ -1191,7 +1196,7 @@ void EndpointAppPBX::out_setup(void) SCPY(dialinginfo.number, e_dialinginfo.number); dialinginfo.itype = INFO_ITYPE_SIP; dialinginfo.ntype = e_dialinginfo.ntype; - portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type); + portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, 0); if (!portlist) { PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial); @@ -1295,7 +1300,7 @@ void EndpointAppPBX::out_setup(void) SCPY(dialinginfo.number, number); dialinginfo.itype = INFO_ITYPE_EXTERN; dialinginfo.ntype = e_dialinginfo.ntype; - portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type); + portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->is_earlyb); if (!portlist) { PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial); @@ -1583,26 +1588,43 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un e_dtmf = param->setup.dtmf; /* check where the call is from */ - if ((param->setup.port_type&PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_DSS1) + if (e_callerinfo.interface[0]) { interface = interface_first; while(interface) { - if (param->setup.isdn_port>=0 && param->setup.isdn_port<(int)sizeof(interface->ports)) + if (!strcmp(e_callerinfo.interface, interface->name)) { - if (interface->ports[param->setup.isdn_port]) - break; + break; } interface = interface->next; } if (interface) { + /* check for MSN numbers, use first MSN if no match */ + msn1 = NULL; + ifmsn = interface->ifmsn; + while(ifmns) + { + if (!msn1) + msn1 = ifmns->msn; + if (!strcmp(ifmns->mns, e_callerinfo.id)) + { + break; + } + ifmsn = ifmsn->next; + } + if (!ifmns && mns1) // not in list, first msn given + SCPY(p_callerinfo.id, msn1); + /* interface is known */ if (interface->iftype==IF_INTERN) { + /* interface is internal */ if (interface->extensions[0]) { + hier denken /* extensions are assigned to interface */ p = interface->extensions; extension1[0] = '\0'; @@ -2025,7 +2047,7 @@ void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, e_dialing_queue[0] = '\0'; } /* check if pattern is available */ - if (!ea_endpoint->ep_portlist->next && portlist->port_type==PORT_TYPE_DSS1_TE_OUT) /* one port_list relation and outgoing external*/ + if (!ea_endpoint->ep_portlist->next && portlist->earlyb) /* one port_list relation and tones available */ { /* indicate patterns */ message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN); @@ -2038,7 +2060,7 @@ void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, } else { /* indicate no patterns */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN); + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN); message_put(message); /* disconnect audio, if not already */ @@ -2069,7 +2091,7 @@ void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_typ ); e_state = EPOINT_STATE_OUT_PROCEEDING; /* check if pattern is availatle */ - if (!ea_endpoint->ep_portlist->next && (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and outgoing external*/ + if (!ea_endpoint->ep_portlist->next && (portlist->earlyb || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */ { /* indicate patterns */ message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN); @@ -2082,7 +2104,7 @@ void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_typ } else { /* indicate no patterns */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN); + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN); message_put(message); /* disconnect audio, if not already */ @@ -2112,7 +2134,7 @@ void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, ); new_state(EPOINT_STATE_OUT_ALERTING); /* check if pattern is available */ - if (!ea_endpoint->ep_portlist->next && (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and outgoing external*/ + if (!ea_endpoint->ep_portlist->next && (portlist->earlyb || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */ { /* indicate patterns */ message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN); @@ -2193,8 +2215,7 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, SCPY(e_terminal_interface, e_connectinfo.interfaces); /* for internal and am calls, we get the extension's id */ - /* also for hidden calls to extension */ - if (portlist->port_type==PORT_TYPE_DSS1_NT_OUT || portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE) + if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE) { SCPY(e_connectinfo.id, e_ext.callerid); SCPY(e_connectinfo.intern, e_terminal); @@ -2468,8 +2489,7 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes int haspatterns = 0; /* check if pattern is available */ if (ea_endpoint->ep_portlist) - if (!ea_endpoint->ep_portlist->next) - if ((ea_endpoint->ep_portlist->port_type==PORT_TYPE_DSS1_TE_OUT) || (ea_endpoint->ep_portlist->port_type==PORT_TYPE_DSS1_TE_IN)) + if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->earlyb) #warning wie ist das bei einem asterisk, gibts auch tones? if (callpbx_countrelations(ea_endpoint->ep_call_id)==2 // we must count relations, in order not to disturb the conference ; NOTE: && message_type != MESSAGE_RELEASE) // if we release, we are done @@ -3624,10 +3644,11 @@ void EndpointAppPBX::ea_message_call(unsigned long call_id, int message_type, un message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL); message->param.channel = CHANNEL_STATE_CONNECT; message_put(message); - /* tell remote epoint to connect audio also, because we like to hear the patterns */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_REMOTE_AUDIO); - message->param.channel = CHANNEL_STATE_CONNECT; - message_put(message); +// /* tell remote epoint to connect audio also, because we like to hear the patterns */ +// message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_REMOTE_AUDIO); +// message->param.channel = CHANNEL_STATE_CONNECT; +// message_put(message); +// patterns are available, remote already connected audio } break; @@ -3645,6 +3666,7 @@ void EndpointAppPBX::ea_message_call(unsigned long call_id, int message_type, un } break; +#if 0 /* CALL (dunno at the moment) */ case MESSAGE_REMOTE_AUDIO: PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received audio remote request.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id); @@ -3652,6 +3674,7 @@ void EndpointAppPBX::ea_message_call(unsigned long call_id, int message_type, un message->param.channel = param->channel; message_put(message); break; +#endif /* CALL sends a notify message */ case MESSAGE_NOTIFY: @@ -3974,7 +3997,7 @@ void EndpointAppPBX::join_call(void) if (other_port) /* port still exists */ { if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT - || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is internal isdn */ + || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */ { other_pdss1 = (class Pdss1 *)other_port; 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); diff --git a/dss1.cpp b/dss1.cpp index e146653..cbfc822 100644 --- a/dss1.cpp +++ b/dss1.cpp @@ -36,7 +36,7 @@ extern "C" { */ Pdss1::Pdss1(int type, mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive) : PmISDN(type, mISDNport, portname, settings, channel, exclusive) { - p_callerinfo.itype = INFO_ITYPE_ISDN; + p_callerinfo.itype = (mISDNport->ifport->interface->extension)?INFO_ITYPE_ISDN:INFO_ITYPE_ISDN_EXTENSION; p_m_d_ntmode = mISDNport->ntmode; p_m_d_l3id = 0; p_m_d_ces = -1; @@ -399,6 +399,22 @@ void Pdss1::setup_ind(unsigned long prim, unsigned long dinfo, void *data) class Endpoint *epoint; struct message *message; + /* if blocked, release call */ + if (p_m_mISDNport->ifport->block) + { + RELEASE_COMPLETE_t *release_complete; + + printlog("--- port#%d is blocked.\n", mISDNport->ifport->portnum); + dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, dinfo, sizeof(RELEASE_COMPLETE_t), p_m_d_ntmode); + isdn_show_send_message(CC_RELEASE_COMPLETE | REQUEST, dmsg); + release_complete = (RELEASE_COMPLETE_t *)(dmsg->data + headerlen); + enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_d_ntmode)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 27); /* temporary unavailable */ + msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); + new_state(PORT_STATE_RELEASE); + p_m_delete = 1; + return; + } + /* caller information */ dec_ie_calling_pn(setup->CALLING_PN, (Q931_info_t *)((unsigned long)data+headerlen), &type, &plan, &present, &screen, (unsigned char *)p_callerinfo.id, sizeof(p_callerinfo.id)); switch (present) @@ -590,7 +606,7 @@ void Pdss1::setup_ind(unsigned long prim, unsigned long dinfo, void *data) break; } - /* channel_id */ jolly todo + /* channel_id */ dec_ie_channel_id(setup->CHANNEL_ID, (Q931_info_t *)((unsigned long)data+headerlen), &exclusive, &channel); if (exclusive<0) exclusive = 0; @@ -598,6 +614,12 @@ void Pdss1::setup_ind(unsigned long prim, unsigned long dinfo, void *data) PDEBUG(DEBUG_BCHANNEL, "- no channel is given by the network, causing to fail, since CW is not possible for external lines\n"); if (channel <= 0) /* not given, no channel, whatever.. */ channel = CHANNEL_ANY; /* any channel */ + if (p_m_mISDNport->b_reserved >= p_m_mISDNport->b_num) // of out chan.. + { + printlog("--- port#%d all channels are used/reserved.\n", ifport->portnum); + ret = -34; // no channel + goto no_channel; + } if (channel == CHANNE_ANY) { PDEBUG(DEBUG_BCHANNEL, "- any channel is assumed from the %s, so we need to return the a channel from our list\n", (p_m_d_ntmode)?"user":"network"); @@ -618,7 +640,7 @@ void Pdss1::setup_ind(unsigned long prim, unsigned long dinfo, void *data) if (mISDNport->b_port[i] == NULL) { channel = i+1+(i>=15); - //printlog("%3d port#%d position %d selecting free channel %d\n", ea_endpoint->ep_serial, ifport_start->portnum, index, *channel); + printlog("--- port#%d no channel given, so selecting free channel %d\n", ifport->portnum, channel); break; } i++; @@ -634,108 +656,123 @@ void Pdss1::setup_ind(unsigned long prim, unsigned long dinfo, void *data) if (mISDNport->b_port[i] == NULL) { channel = selchannel->channel; - //printlog("%3d port#%d position %d selecting given channel %d\n", ea_endpoint->ep_serial, ifport_start->portnum, index, *channel); + printlog("--- port#%d no channel given, so selecting channel %d from list\n", ifport->portnum, channel); break; } break; } if (channel) break; /* found channel */ - //printlog("%3d port#%d position %d skipping, because no channel found.\n", ea_endpoint->ep_serial, ifport_start->portnum, index); selchannel = selchannel->next; } if (!channel) { + printlog("--- port#%d no channel found.\n", ifport->portnum); ret = -34; // no channel goto no_channel; } + goto use_channel; } if (channel > 0) + { /* check for given channel in selection list */ selchannel = ifport->channel_in; while(selchannel) { if (selchannel->channel == channel || selchannel->channel == CHANNEL_FREE) break; - //printlog("%3d port#%d position %d skipping, because no channel found.\n", ea_endpoint->ep_serial, ifport_start->portnum, index); selchannel = selchannel->next; } if (!selchannel) channel = 0; + /* exclusive channel requests must be in the list */ if (exclusive) { if (!channel) { PDEBUG(DEBUG_BCHANNEL, "- exclusive channel %d is selected, but not in list of incomming channel.\n", channel); + printlog("--- port#%d channel %d given exclusively, it is accepted.\n", ifport->portnum, channel); ret = 6; // unacceptable goto no_channel; } PDEBUG(DEBUG_BCHANNEL, "- exclusive channel %d is selected, as in list of incomming channels.\n", channel); - } else + i = selchannel->channel-1-(selchannel->channel>=17); + if (mISDNport->b_port[i] == NULL) + { + printlog("--- port#%d channel %d given exclusively, it is accepted and free.\n", ifport->portnum, channel); + goto use_channel; + } + printlog("--- port#%d channel %d given exclusively, it is accepted, but busy.\n", ifport->portnum, channel); + ret = 6; // unacceptable + goto no_channel; + } + + /* requested channels in list will be used */ if (channel) { PDEBUG(DEBUG_BCHANNEL, "- channel %d given, found in list.\n", channel); i = selchannel->channel-1-(selchannel->channel>=17); if (mISDNport->b_port[i] == NULL) { + printlog("--- port#%d channel %d given, it is accepted and free.\n", ifport->portnum, channel); goto use_channel; } - goto inuse_search_differnt; - } else - { - inuse_search_different: - PDEBUG(DEBUG_BCHANNEL, "- channel %d given, but not in list of incomming channels.\n", channel); + } + + /* if channel is not available or not in list, it must be searched */ + PDEBUG(DEBUG_BCHANNEL, "- channel %d given, but not in list of incomming channels.\n", channel); - /* check for first free channel in list */ - selchannel = ifport->channel_in; - while(selchannel) + /* check for first free channel in list */ + channel = 0; + selchannel = ifport->channel_in; + while(selchannel) + { + switch(selchannel->channel) { - switch(selchannel->channel) + case CHANNEL_FREE: /* free channel */ + if (mISDNport->b_inuse >= mISDNport->b_num) + break; /* all channel in use or reserverd */ + /* find channel */ + i = 0; + while(i < mISDNport->b_num) { - case CHANNEL_FREE: /* free channel */ - if (mISDNport->b_inuse >= mISDNport->b_num) - break; /* all channel in use or reserverd */ - /* find channel */ - i = 0; - while(i < mISDNport->b_num) - { - if (mISDNport->b_port[i] == NULL) - { - channel = i+1+(i>=15); - //printlog("%3d port#%d position %d selecting free channel %d\n", ea_endpoint->ep_serial, ifport_start->portnum, index, *channel); - break; - } - i++; - } - break; - - default: - if (selchannel->channel<1 || selchannel->channel==16) - break; /* invalid channels */ - i = selchannel->channel-1-(selchannel->channel>=17); - if (i >= mISDNport->b_num) - break; /* channel not in port */ if (mISDNport->b_port[i] == NULL) { - channel = selchannel->channel; - //printlog("%3d port#%d position %d selecting given channel %d\n", ea_endpoint->ep_serial, ifport_start->portnum, index, *channel); + channel = i+1+(i>=15); + printlog("--- port#%d requested channel was not in list, so using free channel %d from list.\n", ifport->portnum, channel); break; } + i++; + } + break; + + default: + if (selchannel->channel<1 || selchannel->channel==16) + break; /* invalid channels */ + i = selchannel->channel-1-(selchannel->channel>=17); + if (i >= mISDNport->b_num) + break; /* channel not in port */ + if (mISDNport->b_port[i] == NULL) + { + channel = selchannel->channel; + printlog("--- port#%d requested channel was not in list, so using free channel %d from list.\n", ifport->portnum, channel); break; } - if (channel) - break; /* found channel */ - //printlog("%3d port#%d position %d skipping, because no channel found.\n", ea_endpoint->ep_serial, ifport_start->portnum, index); - selchannel = selchannel->next; - } - if (!channel) - { - ret = 6; // unacceptable - goto no_channel; + break; } + if (channel) + break; /* found channel */ + selchannel = selchannel->next; } -channel wählen + if (!channel) + { + printlog("--- port#%d no channel found.\n", ifport->portnum); + ret = 6; // unacceptable + goto no_channel; + } + } + /* open channel */ use_channel: ret = seize_bchannel(channel, 1); @@ -754,7 +791,9 @@ channel w p_m_delete = 1; return; } - PDEBUG(DEBUG_BCHANNEL, "- channel is available, we selected channel %d.\n", ret); + PDEBUG(DEBUG_BCHANNEL, "- channel is available, we open channel %d.\n", ret); + bchannel_activate(p_m_mISDNport, p_m_b_index); + /* create endpoint */ if (p_epointlist) { @@ -800,6 +839,7 @@ channel w PDEBUG(DEBUG_ISDN, "Pdss1(%s) nt-mode gives us new l3id via setup ind: 0x%x\n", p_name, p_m_d_l3id); } + /* send setup message to endpoit */ PDEBUG(DEBUG_ISDN, "Pdss1(%s) setup: %s->%s\n", p_name, p_callerinfo.id, p_dialinginfo.number); message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP); message->param.setup.isdn_port = p_m_portnum; @@ -1161,13 +1201,13 @@ void Pdss1::disconnect_ind(unsigned long prim, unsigned long dinfo, void *data) if (cause < 0) cause = 16; - /* release if we are internal, since internal TEs don't send tones */ - if (p_m_d_ntmode) // || !options.inbandpattern) + /* release if we are remote sends us no tones */ + if (p_m_mISDNport->is_earlyb) { RELEASE_t *release; msg_t *dmsg; - PDEBUG(DEBUG_ISDN, "Pdss1(%s) send release because internal phone disconnects OR inbandpatterns are not enabled.\n", p_name); + PDEBUG(DEBUG_ISDN, "Pdss1(%s) send release because remote disconnects AND provides no patterns (earlyb).\n", p_name); dmsg = create_l3msg(CC_RELEASE | REQUEST, MT_RELEASE, dinfo, sizeof(RELEASE_t), p_m_d_ntmode); isdn_show_send_message(CC_RELEASE | REQUEST, dmsg); release = (RELEASE_t *)(dmsg->data + headerlen); @@ -1620,6 +1660,16 @@ void Pdss1::resume_ind(unsigned long prim, unsigned long dinfo, void *data) struct message *message; int ret; + /* if blocked, release call */ + if (p_m_mISDNport->ifport->block) + { + RELEASE_COMPLETE_t *release_complete; + + printlog("--- port#%d is blocked.\n", mISDNport->ifport->portnum); + ret = -27; + goto reject; + } + /* call id */ dec_ie_call_id(resume->CALL_ID, (Q931_info_t *)((unsigned long)data+headerlen), callid, &len); if (len<0) len = 0; @@ -1675,7 +1725,7 @@ void Pdss1::resume_ind(unsigned long prim, unsigned long dinfo, void *data) PERROR("no memory for epointlist\n"); exit(-1); } - if (!(epoint->portlist_new(p_serial, p_type))) + if (!(epoint->portlist_new(p_serial, p_type, p_m_mISDNport->is_earlyb))) { PERROR("no memory for portlist\n"); exit(-1); @@ -2099,6 +2149,18 @@ void Pdss1::message_setup(unsigned long epoint_id, int message_id, union paramet int i; struct epoint_list *epointlist; + /* release if port is blocked */ + if (p_m_mISDNport->ifport->block) + { + message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE); + message->param.disconnectinfo.cause = 27; // temp. unavail. + message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + message_put(message); + new_state(PORT_STATE_RELEASE); + p_m_delete = 1; + return; + } + /* copy setup infos to port */ memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo)); memcpy(&p_dialinginfo, ¶m->setup.dialinginfo, sizeof(p_dialinginfo)); @@ -2513,7 +2575,7 @@ void Pdss1::message_overlap(unsigned long epoint_id, int message_id, union param if (p_capainfo.bearer_capa==INFO_BC_SPEECH || p_capainfo.bearer_capa==INFO_BC_AUDIO || p_capainfo.bearer_capa==INFO_BC_DATAUNRESTRICTED_TONES) - if (p_m_d_ntmode || options.inbandpattern) + if (p_m_mISDNport->is_tones) enc_ie_progress(&setup_acknowledge->PROGRESS, dmsg, 0, p_m_d_ntmode?1:5, 8); msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); @@ -2538,7 +2600,7 @@ void Pdss1::message_proceeding(unsigned long epoint_id, int message_id, union pa if (p_capainfo.bearer_capa==INFO_BC_SPEECH || p_capainfo.bearer_capa==INFO_BC_AUDIO || p_capainfo.bearer_capa==INFO_BC_DATAUNRESTRICTED_TONES) - if (p_m_d_ntmode || options.inbandpattern) + if (p_m_mISDNport->is_tones) enc_ie_progress(&proceeding->PROGRESS, dmsg, 0, p_m_d_ntmode?1:5, 8); msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); @@ -2583,7 +2645,7 @@ void Pdss1::message_alerting(unsigned long epoint_id, int message_id, union para if (p_capainfo.bearer_capa==INFO_BC_SPEECH || p_capainfo.bearer_capa==INFO_BC_AUDIO || p_capainfo.bearer_capa==INFO_BC_DATAUNRESTRICTED_TONES) - if (p_m_d_ntmode || options.inbandpattern) + if (p_m_mISDNport->is_tones) enc_ie_progress(&alerting->PROGRESS, dmsg, 0, p_m_d_ntmode?1:5, 8); msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); @@ -2727,8 +2789,8 @@ void Pdss1::message_disconnect(unsigned long epoint_id, int message_id, union pa struct message *message; char *p = NULL; - /* we reject during incoming setup when we have no inbandpatterns. also if we are in outgoing setup state */ - if ((!p_m_d_ntmode && p_state==PORT_STATE_IN_SETUP && !options.inbandpattern) + /* we reject during incoming setup when we have no tones. also if we are in outgoing setup state */ + if ((p_state==PORT_STATE_IN_SETUP && !p_m_mISDNport->is_tones) || p_state==PORT_STATE_OUT_SETUP) { /* sending release to endpoint */ @@ -2781,7 +2843,7 @@ void Pdss1::message_disconnect(unsigned long epoint_id, int message_id, union pa if (p_capainfo.bearer_capa==INFO_BC_SPEECH || p_capainfo.bearer_capa==INFO_BC_AUDIO || p_capainfo.bearer_capa==INFO_BC_DATAUNRESTRICTED_TONES) - if (p_m_d_ntmode || options.inbandpattern) + if (p_m_mISDNport->is_tones) enc_ie_progress(&disconnect->PROGRESS, dmsg, 0, p_m_d_ntmode?1:5, 8); /* send cause */ enc_ie_cause(&disconnect->CAUSE, dmsg, (p_m_d_ntmode && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause); @@ -2875,7 +2937,7 @@ void Pdss1::message_release(unsigned long epoint_id, int message_id, union param if (p_capainfo.bearer_capa==INFO_BC_SPEECH || p_capainfo.bearer_capa==INFO_BC_AUDIO || p_capainfo.bearer_capa==INFO_BC_DATAUNRESTRICTED_TONES) - if (p_m_d_ntmode || options.inbandpattern) + if (p_m_mISDNport->is_tones) enc_ie_progress(&disconnect->PROGRESS, dmsg, 0, p_m_d_ntmode?1:5, 8); /* send cause */ enc_ie_cause(&disconnect->CAUSE, dmsg, (p_m_d_ntmode && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause); diff --git a/endpoint.cpp b/endpoint.cpp index 3f67f41..39cba95 100644 --- a/endpoint.cpp +++ b/endpoint.cpp @@ -43,6 +43,7 @@ Endpoint::Endpoint(int port_id, int call_id) { class Port *port; class Endpoint **epointpointer; + int earlyb = 0; /* epoint structure */ PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Allocating enpoint %d and connecting it with:%s%s\n", epoint_serial, epoint_serial, (port_id)?" ioport":"", (call_id)?" call":""); @@ -66,10 +67,14 @@ Endpoint::Endpoint(int port_id, int call_id) { port = find_port_id(port_id); if (port) - if (!portlist_new(port_id, port->p_type)) { - PERROR("no mem for portlist, exitting...\n"); - exit(-1); + if ((port->p_type&PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_DSS1) + earlyb = port->mISDNport->is_earlyb; + if (!portlist_new(port_id, port->p_type, earlyb)) + { + PERROR("no mem for portlist, exitting...\n"); + exit(-1); + } } } ep_call_id = call_id; @@ -140,7 +145,7 @@ Endpoint::~Endpoint(void) /* create new portlist relation */ -struct port_list *Endpoint::portlist_new(unsigned long port_id, int port_type) +struct port_list *Endpoint::portlist_new(unsigned long port_id, int port_type, int earlyb) { struct port_list *portlist, **portlistpointer; @@ -165,6 +170,7 @@ struct port_list *Endpoint::portlist_new(unsigned long port_id, int port_type) /* link to call or port */ portlist->port_id = port_id; portlist->port_type = port_type; + portlist->earlyb = earlyb; return(portlist); } diff --git a/endpoint.h b/endpoint.h index 506689a..e556bf3 100644 --- a/endpoint.h +++ b/endpoint.h @@ -15,6 +15,7 @@ struct port_list { struct port_list *next; unsigned long port_id; int port_type; + int early_b; /* if patterns are available */ }; /* structure of an Enpoint */ diff --git a/interface.c b/interface.c index 8ff0932..520ecbd 100644 --- a/interface.c +++ b/interface.c @@ -158,6 +158,11 @@ static int inter_ptp(struct interface *interface, char *filename, int line, char SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter); return(-1); } + if (interface->ifport->ptmp) + { + SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptmp was given.\n", filename, line, parameter); + return(-1); + } /* goto end of chain */ ifport = interface->ifport; while(ifport->next) @@ -171,6 +176,34 @@ static int inter_ptp(struct interface *interface, char *filename, int line, char ifport->ptp = 1; return(0); } +static int inter_ptmp(struct interface *interface, char *filename, int line, char *parameter, char *value) +{ + struct interface_port *ifport; + + /* port in chain ? */ + if (!interface->ifport) + { + SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter); + return(-1); + } + if (interface->ifport->ptp) + { + SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptp was given.\n", filename, line, parameter); + return(-1); + } + /* goto end of chain */ + ifport = interface->ifport; + while(ifport->next) + ifport = ifport->next; + /* add value */ + if (value[0]) + { + SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter); + return(-1); + } + ifport->ptmp = 1; + return(0); +} static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value) { if (!strcasecmp(value, "yes")) @@ -641,6 +674,11 @@ struct interface_param interface_param[] = { "This is required on NT-mode ports that are multipoint by default.\n" "This parameter must follow a 'port' parameter."}, + {"ptmp", &inter_ptmp, "", + "The given port above is opened as point-to-multipoint.\n" + "This is required on PRI NT-mode ports that are point-to-point by default.\n" + "This parameter must follow a 'port' parameter."}, + {"channel_out", &inter_channel_out, "[force,][][,...][,free][,any][,no]", "Channel selection list for all outgoing calls to the interface.\n" "A free channels is searched in order of appearance.\n" @@ -1010,15 +1048,29 @@ void relink_interfaces(void) if (!ifport->mISDNport) { /* open new port */ - mISDNport = mISDNport_open(ifport->portnum, ifport->ptp); + mISDNport = mISDNport_open(ifport->portnum, ifport->ptp, ifport->ptmp); if (mISDNport) { ifport->mISDNport = mISDNport; mISDNport->ifport = ifport; } } - if (ifport->mISDNport && !ifport->selchannel) - default_selchannel(ifport); + if (ifport->mISDNport) + { + /* default channel selection list */ + if (!ifport->selchannel) + default_selchannel(ifport); + /* default is_tones */ + if (ifport->interface->is_tones) + ifport->mISDNport->is_tones = (ifport->interface->is_tones==IS_YES); + else + ifport->mISDNport->is_tones = (ifport->mISDNport->ntmode)?1:0; + /* default is_earlyb */ + if (ifport->interface->is_earlyb) + ifport->mISDNport->is_earlyb = (ifport->interface->is_earlyb==IS_YES); + else + ifport->mISDNport->is_earlyb = (ifport->mISDNport->ntmode)?0:1; + } } interface = interface->next; } diff --git a/interface.h b/interface.h index f7d56c9..e1a18b5 100644 --- a/interface.h +++ b/interface.h @@ -52,7 +52,6 @@ struct interface_port { int channel_force; /* forces channel by protocol */ struct select_channel *out_select; /* list of channels to select */ struct select_channel *in_select; /* the same for incoming channels */ -// int open; /* set if port is opened */ int block; /* set if interface is blocked */ }; diff --git a/mISDN.cpp b/mISDN.cpp index 5bb09d1..40d5204 100644 --- a/mISDN.cpp +++ b/mISDN.cpp @@ -550,12 +550,11 @@ void PmISDN::bchannel_receive(iframe_t *frm) return; } - /* external incoming calls will not process any audio data unless - * the call is connected OR inbandpattern feature is enabled. + /* calls will not process any audio data unless + * the call is connected OR tones feature is enabled. */ - if (p_type==PORT_TYPE_DSS1_TE_IN - && p_state!=PORT_STATE_CONNECT - && !options.inbandpattern) + if (p_state!=PORT_STATE_CONNECT + && !p_m_mISDNport->is_tones) return; #if 0 @@ -1388,7 +1387,7 @@ int mISDN_handler(void) /* * global function to add a new card (port) */ -struct mISDNport *mISDN_port_open(int port, int ptp) +struct mISDNport *mISDN_port_open(int port, int ptp, int ptmp) { int ret; unsigned char buff[1025]; @@ -1564,6 +1563,11 @@ struct mISDNport *mISDN_port_open(int port, int ptp) { PDEBUG(DEBUG_ISDN, "Port is point-to-point.\n"); mISDNport->ptp = ptp = 1; + if (ptmp && nt) + { + PDEBUG(DEBUG_ISDN, "Port is forced to point-to-multipoint.\n"); + mISDNport->ptp = ptp = 0; + } } i = 0; while(i < stinf->childcnt) diff --git a/mISDN.h b/mISDN.h index a82933b..20937e4 100644 --- a/mISDN.h +++ b/mISDN.h @@ -36,6 +36,8 @@ struct mISDNport { int use; /* counts the number of port that uses this port */ int ntmode; /* is TRUE if port is nt mode */ int pri; /* is TRUE if port is a primary rate interface */ + int is_tones; /* TRUE if tones are sent outside connect state */ + int is_earlyb; /* TRUE if tones are received outside connect state */ int upper_id; /* id to transfer data down */ int lower_id; /* id to transfer data up */ int d_stid; diff --git a/message.h b/message.h index 0a56b98..e95e8e7 100644 --- a/message.h +++ b/message.h @@ -1,6 +1,6 @@ /*****************************************************************************\ ** ** -** PBX4Linux ** +** Linux Call Router ** ** ** **---------------------------------------------------------------------------** ** Copyright: Andreas Eversberg ** @@ -127,8 +127,7 @@ enum { /* isdnsignal */ /* call-info structure CALLER */ struct caller_info { char id[32]; /* id of caller (user number) */ - char voip[64]; /* URI of voip (or gateway) */ - char intern[32]; /* internal id */ + char extension[32]; /* internal id */ char name[16]; int isdn_port; /* internal/external port (if call is isdn) */ char interface[32]; /* interface name the call was from */ @@ -221,7 +220,7 @@ struct useruser_info { /* call-info structure SETUP */ struct message_setup { - int isdn_port; /* card number 1...n (only on calls from internal isdn port) */ + int isdn_port; /* card number 1...n (only on calls from isdn port) */ int port_type; /* type of port (only required if message is port -> epoint) */ int dtmf; /* used to enabled dtmf dialing at setup state */ int partyline; /* if set, call will be a conference room */ @@ -341,7 +340,7 @@ enum { /* messages between entities */ MESSAGE_RESUME, /* resume port */ MESSAGE_CHANNEL, /* set status of audio path to endpoint (to call, audio is also set) */ - MESSAGE_REMOTE_AUDIO, /* tell remote to set audio status */ +// MESSAGE_REMOTE_AUDIO, /* tell remote to set audio status */ MESSAGE_PATTERN, /* pattern information tones available */ MESSAGE_NOPATTERN, /* pattern information tones unavailable */ MESSAGE_CRYPT, /* encryption message */ @@ -375,7 +374,7 @@ enum { /* messages between entities */ "MESSAGE_SUSPEND", \ "MESSAGE_RESUME", \ "MESSAGE_CHANNEL", \ - "MESSAGE_REMOTE_AUDIO", \ +/* "MESSAGE_REMOTE_AUDIO",*/ \ "MESSAGE_PATTERN", \ "MESSAGE_NOPATTERN", \ "MESSAGE_CRYPT", \ diff --git a/options.c b/options.c index d41680e..bd4e002 100644 --- a/options.c +++ b/options.c @@ -39,7 +39,6 @@ struct options options = { 5060, 5, /* SIP port, maxqueue */ 0, /* dtmf detection on */ "", /* dummy caller id */ - 0, /* inband patterns on external calls */ 0, /* use tones by dsp.o */ 0, /* by default use priority 0 */ "pbx@jolly.de" /* source mail adress */ @@ -415,13 +414,6 @@ int read_options(void) PDEBUG(DEBUG_CONFIG, "dummy caller id\n", param); } else - if (!strcmp(option,"inbandpattern")) - { - if (!strcasecmp(param, "yes")) - options.inbandpattern = 1; - - PDEBUG(DEBUG_CONFIG, "inband pattern = %s\n", (options.inbandpattern)?"yes":"no"); - } else if (!strcmp(option,"dsptones")) { if (!strcasecmp(param, "american")) diff --git a/options.h b/options.h index 52c2c52..90270c6 100644 --- a/options.h +++ b/options.h @@ -46,7 +46,6 @@ struct options { int sip_maxqueue; int nodtmf; /* use dtmf detection */ char dummyid[32]; /* caller id for external calls if not available */ - int inbandpattern; /* inband patterns on external calls */ int dsptones; /* tones will be generated via dsp.o 1=american 2=ger */ int schedule; /* run process in realtime @ given priority */ char email[128]; /* source email address */ diff --git a/todo.txt b/todo.txt index cedebe3..131a13c 100644 --- a/todo.txt +++ b/todo.txt @@ -1,19 +1,28 @@ +define and change dsp conference ids make asterisk call implementation -interface.conf neu +new interface.conf -mixer abspecken +reduce mixer call recording -call zu mehreren extensions - - +call to multiple endpoints (extensions) +trace with layers and filters + - layer 1 and 2 state changes and messages + - layer 3 isdn trace, process ids + - messages between port, endpoint and call + - port hunt and channel selection + - dialing / routing + - application process (action) + - bchannel control (tones, dsp, filter, activation/deactivation) +sip raus, h323 raus +avoid disconnect-collision (release if disconnect from both sides) -- 2.13.6