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));
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);
}
class Endpoint *epoint;
struct port_list *portlist;
class Port *port;
+ unsigned int bridge_id;
#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 */
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
&& 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 {
message_put(message);
}
- /*
- * Bridge between port instances if:
- * - two relations
- * - one or all are not mISDN
- */
- message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_BRIDGE);
- message->param.bridge_id = (relations==2 && !allmISDN) ? j_serial : 0;
- 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) {
}
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);