X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=joinpbx.cpp;h=5d88fa232b8341121b467b143e00a2bc55269376;hp=6440f5871d2a034a6416ce25cc6fbc87a2a8ce12;hb=fa1f601f49879958ac9fc698b044012c772ec7da;hpb=74a7fe54a81bb7e996ea45203bbc8cc0ff6b8dda diff --git a/joinpbx.cpp b/joinpbx.cpp index 6440f58..5d88fa2 100644 --- a/joinpbx.cpp +++ b/joinpbx.cpp @@ -226,6 +226,7 @@ JoinPBX::JoinPBX(class Endpoint *epoint) : Join() j_pid = getpid(); j_partyline = 0; j_partyline_jingle = 0; + j_3pty = 0; j_multicause = 0; j_multilocation = 0; memset(&j_updatebridge, 0, sizeof(j_updatebridge)); @@ -261,6 +262,19 @@ JoinPBX::~JoinPBX() relation = rtemp; } + /* remove 3PTY from other join */ + if (j_3pty) { + class Join *join; + class JoinPBX *joinpbx; + + join = find_join_id(j_3pty); + if (join && join->j_type == JOIN_TYPE_PBX) { + joinpbx = (class JoinPBX *)join; + joinpbx->j_3pty = 0; + trigger_work(&joinpbx->j_updatebridge); + } + } + del_work(&j_updatebridge); } @@ -285,12 +299,23 @@ void JoinPBX::bridge(void) class Endpoint *epoint; struct port_list *portlist; class Port *port; + unsigned int bridge_id; + class Join *join_3pty; + class JoinPBX *joinpbx_3pty; #ifdef DEBUG_COREBRIDGE int allmISDN = 0; // never set for debug purpose #else int allmISDN = 1; // set until a non-mISDN relation is found #endif + /* bridge id is the serial of join + * if we have a 3pty with another join, we always use the lowest brigde id. + * this way we use common ids, so both joins share same bridge */ + if (j_3pty && j_3pty < j_serial) + bridge_id = j_3pty; + else + bridge_id = j_serial; + relation = j_relation; while(relation) { /* count all relations */ @@ -333,10 +358,65 @@ void JoinPBX::bridge(void) relation = relation->next; continue; } - + relation = relation->next; } + /* check if 3pty members have no mISDN, so bridging via mISDN/lcr will be selected correctly */ + join_3pty = find_join_id(j_3pty); + if (join_3pty && join_3pty->j_type == JOIN_TYPE_PBX) { + joinpbx_3pty = (class JoinPBX *)join_3pty; + relation = joinpbx_3pty->j_relation; + while(relation) { + +#if 0 +no need to count, because j_3pty is taken into account below when checking relations + /* count all relations */ + relations++; +#endif + + /* check for relation's objects */ + epoint = find_epoint_id(relation->epoint_id); + if (!epoint) { + PERROR("software error: relation without existing endpoints.\n"); + relation = relation->next; + continue; + } + portlist = epoint->ep_portlist; + if (!portlist) { + PDEBUG(DEBUG_JOIN, "other 3pty join %d: ignoring relation without port object.\n", joinpbx_3pty->j_serial); +//#warning testing: keep on hold until single audio stream available + relation->channel_state = 0; + relation = relation->next; + continue; + } + if (portlist->next) { + PDEBUG(DEBUG_JOIN, "other 3pty join %d: ignoring relation with ep%d due to port_list.\n", joinpbx_3pty->j_serial, epoint->ep_serial); +//#warning testing: keep on hold until single audio stream available + relation->channel_state = 0; + relation = relation->next; + continue; + } + port = find_port_id(portlist->port_id); + if (!port) { + PDEBUG(DEBUG_JOIN, "other 3pty join %d: ignoring relation without existing port object.\n", joinpbx_3pty->j_serial); + relation = relation->next; + continue; + } + if ((port->p_type&PORT_CLASS_MASK)!=PORT_CLASS_mISDN) { + PDEBUG(DEBUG_JOIN, "other 3pty join %d: ignoring relation ep%d because it's port is not mISDN.\n", joinpbx_3pty->j_serial, epoint->ep_serial); + if (allmISDN) { + PDEBUG(DEBUG_JOIN, "other 3pty join %d: not all endpoints are mISDN.\n", joinpbx_3pty->j_serial); + allmISDN = 0; + } + relation = relation->next; + continue; + } + + relation = relation->next; + } + } + PDEBUG(DEBUG_JOIN, "join%d members=%d %s\n", j_serial, relations, (allmISDN)?"(all are mISDN-members)":"(not all are mISDN-members)"); /* we notify all relations about rxdata. */ relation = j_relation; @@ -348,6 +428,8 @@ void JoinPBX::bridge(void) numconnect ++; /* remove unconnected parties from conference, also remove remotely disconnected parties so conference will not be disturbed. */ + + /* mISDN */ if (relation->channel_state == 1 && relation->rx_state != NOTIFY_STATE_HOLD && relation->rx_state != NOTIFY_STATE_SUSPEND @@ -355,7 +437,7 @@ void JoinPBX::bridge(void) && allmISDN) { // no conf if any member is not mISDN message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL); message->param.mISDNsignal.message = mISDNSIGNAL_CONF; - message->param.mISDNsignal.conf = j_serial<<16 | j_pid; + message->param.mISDNsignal.conf = (bridge_id << 16) | j_pid; PDEBUG(DEBUG_JOIN, "join%d EP%d +on+ id: 0x%08x\n", j_serial, relation->epoint_id, message->param.mISDNsignal.conf); message_put(message); } else { @@ -366,27 +448,35 @@ void JoinPBX::bridge(void) message_put(message); } - /* - * Bridge between port instances if: - * - one or all are not mISDN - */ - message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_BRIDGE); - message->param.bridge_id = j_serial; - PDEBUG(DEBUG_JOIN, "join%u EP%u requests bridge=%u\n", j_serial, relation->epoint_id, message->param.bridge_id); - message_put(message); + /* core bridge */ + if (relation->channel_state == 1 + && relation->rx_state != NOTIFY_STATE_HOLD + && relation->rx_state != NOTIFY_STATE_SUSPEND + && relations>1 // no bridge with one member + && !allmISDN) { // no bridge if all members are mISDN + message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_BRIDGE); + message->param.bridge_id = bridge_id; + PDEBUG(DEBUG_JOIN, "join%u EP%u requests bridge=%u\n", j_serial, relation->epoint_id, bridge_id); + message_put(message); + } else { + message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_BRIDGE); + message->param.bridge_id = 0; + PDEBUG(DEBUG_JOIN, "join%u EP%u drop bridge=%u\n", j_serial, relation->epoint_id, bridge_id); + message_put(message); + } relation = relation->next; } /* two people just exchange their states */ - if (relations==2 && !j_partyline) { + if (!j_3pty && relations==2 && !j_partyline) { PDEBUG(DEBUG_JOIN, "join%d 2 relations / no partyline\n", j_serial); relation = j_relation; relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, relation->next->rx_state); relation->next->tx_state = notify_state_change(j_serial, relation->next->epoint_id, relation->next->tx_state, relation->rx_state); } else /* one member in a join, so we put her on hold */ - if ((relations==1 || numconnect==1)/* && !j_partyline_jingle*/) { + if (!j_3pty && (relations==1 || numconnect==1)/* && !j_partyline_jingle*/) { PDEBUG(DEBUG_JOIN, "join%d 1 member or only 1 connected, put on hold\n", j_serial); relation = j_relation; while(relation) { @@ -498,9 +588,6 @@ int joinpbx_countrelations(unsigned int join_id) if (!join) return(0); - if (join->j_type == JOIN_TYPE_REMOTE) - return(2); - if (join->j_type != JOIN_TYPE_PBX) return(0); joinpbx = (class JoinPBX *)join; @@ -665,6 +752,26 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par } break; + /* track notify */ + case MESSAGE_NOTIFY: + switch(param->notifyinfo.notify) { + case INFO_NOTIFY_USER_SUSPENDED: + case INFO_NOTIFY_USER_RESUMED: + case INFO_NOTIFY_REMOTE_HOLD: + case INFO_NOTIFY_REMOTE_RETRIEVAL: + case INFO_NOTIFY_CONFERENCE_ESTABLISHED: + case INFO_NOTIFY_CONFERENCE_DISCONNECTED: + new_state = track_notify(relation->rx_state, param->notifyinfo.notify); + if (new_state != relation->rx_state) { + relation->rx_state = new_state; + trigger_work(&j_updatebridge); + if (options.deb & DEBUG_JOIN) + joinpbx_debug(this, "Join::message_epoint{after setting new rx state}"); + } + break; + } + break; + case MESSAGE_DISCONNECT: PDEBUG(DEBUG_JOIN, "releasing after receiving disconnect, because join in partyline mode.\n"); message = message_create(j_serial, epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE); @@ -691,7 +798,7 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par switch(message_type) { /* process audio path message */ case MESSAGE_AUDIOPATH: - PDEBUG(DEBUG_JOIN, "join received channel message: %d.\n", param->audiopath); + PDEBUG(DEBUG_JOIN, "join received channel message: audiopath=%d, current relation's channel_state=%d\n", param->audiopath, relation->channel_state); if (relation->channel_state != param->audiopath) { relation->channel_state = param->audiopath; trigger_work(&j_updatebridge);