PDEBUG(DEBUG_JOIN, "end\n");
}
+int update_bridge(struct lcr_work *work, void *instance, int index);
/*
* constructor for a new join
j_dialed[0] = '\0';
j_todial[0] = '\0';
j_pid = getpid();
- j_updatebridge = 0;
j_partyline = 0;
j_partyline_jingle = 0;
j_multicause = 0;
j_multilocation = 0;
+ memset(&j_updatebridge, 0, sizeof(j_updatebridge));
+ add_work(&j_updatebridge, update_bridge, this, 0);
/* initialize a relation only to the calling interface */
relation = j_relation = (struct join_relation *)MALLOC(sizeof(struct join_relation));
cmemuse--;
relation = rtemp;
}
+
+ del_work(&j_updatebridge);
}
/* bridge sets the audio flow of all bchannels assiociated to 'this' join
* also it changes and notifies active/hold/conference states
*/
+int update_bridge(struct lcr_work *work, void *instance, int index)
+{
+ class JoinPBX *joinpbx = (class JoinPBX *)instance;
+
+ joinpbx->bridge();
+
+ return 0;
+}
+
void JoinPBX::bridge(void)
{
struct join_relation *relation;
/* remove from bridge */
if (relation->channel_state != 0) {
relation->channel_state = 0;
- j_updatebridge = 1; /* update bridge flag */
+ trigger_work(&j_updatebridge);
// note: if join is not released, bridge must be updated
}
if (!join)
return(0);
- if (join->j_type != JOIN_TYPE_REMOTE)
+ if (join->j_type == JOIN_TYPE_REMOTE)
return(2);
if (join->j_type != JOIN_TYPE_PBX)
return(i);
}
+/* check if one is calling and all other relations are setup-realations */
+int joinpbx_onecalling_othersetup(struct join_relation *relation)
+{
+ int calling = 0, other = 0;
+
+ while(relation) {
+ switch(relation->type) {
+ case RELATION_TYPE_CALLING:
+ calling++;
+ break;
+ case RELATION_TYPE_SETUP:
+ break;
+ default:
+ other++;
+ break;
+ }
+
+ relation = relation->next;
+ }
+
+ if (calling == 1 && other == 0)
+ return(1);
+ return(0);
+}
+
void JoinPBX::remove_relation(struct join_relation *relation)
{
struct join_relation *temp, **tempp;
return;
}
+ /* count relations */
+ num=joinpbx_countrelations(j_serial);
+
/* process party line */
if (message_type == MESSAGE_SETUP) if (param->setup.partyline && !j_partyline) {
j_partyline = param->setup.partyline;
SPRINT(message->param.connectinfo.id, "%d", j_partyline);
message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
message_put(message);
- j_updatebridge = 1; /* update bridge flag */
+ trigger_work(&j_updatebridge);
if (j_partyline_jingle)
play_jingle(1);
break;
PDEBUG(DEBUG_JOIN, "join received channel message: %d.\n", param->audiopath);
if (relation->channel_state != param->audiopath) {
relation->channel_state = param->audiopath;
- j_updatebridge = 1; /* update bridge flag */
+ trigger_work(&j_updatebridge);
if (options.deb & DEBUG_JOIN)
joinpbx_debug(this, "Join::message_epoint{after setting new channel state}");
}
PDEBUG(DEBUG_JOIN, "join received channel message: %d.\n", param->audiopath);
if (relation->channel_state != param->audiopath) {
relation->channel_state = param->audiopath;
- j_updatebridge = 1; /* update bridge flag */
+ trigger_work(&j_updatebridge);
if (options.deb & DEBUG_JOIN)
joinpbx_debug(this, "Join::message_epoint{after setting new channel state}");
}
new_state = track_notify(relation->rx_state, param->notifyinfo.notify);
if (new_state != relation->rx_state) {
relation->rx_state = new_state;
- j_updatebridge = 1;
+ trigger_work(&j_updatebridge);
if (options.deb & DEBUG_JOIN)
joinpbx_debug(this, "Join::message_epoint{after setting new rx state}");
}
release(j_relation, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
return; // must return, because join IS destroyed
}
- /* remove all relations that are in called */
+ /* in a conf, we don't kill the other members */
+ if (num > 2 && !joinpbx_onecalling_othersetup(j_relation)) {
+ release(relation, 0, 0);
+ return;
+ }
+ /* remove all relations that are of called type */
release_again2:
reltemp = j_relation;
while(reltemp) {
return; // must return, because join may be destroyed
}
- /* count relations */
- num=joinpbx_countrelations(j_serial);
-
/* check number of relations */
- if (num > 2) {
- PDEBUG(DEBUG_JOIN, "join has more than two relations so there is no need to send a message.\n");
+ if (num > 2 && !joinpbx_onecalling_othersetup(j_relation) && message_type != MESSAGE_CONNECT) {
+ PDEBUG(DEBUG_JOIN, "we are in a conference, so we ignore the messages, except MESSAGE_CONNECT.\n");
return;
}
- /* find interfaces not related to calling epoint */
- relation = j_relation;
- while(relation) {
- if (relation->epoint_id != epoint_id)
- break;
- relation = relation->next;
- }
- if (!relation) {
+ /* if join has no other relation, we process the setup message */
+ if (num == 1) {
switch(message_type) {
case MESSAGE_SETUP:
if (param->setup.dialinginfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
+ /* in case of keypad */
+ numbers = param->setup.dialinginfo.keypad;
+ if (numbers[0]) {
+ while((number = strsep(&numbers, ","))) {
+ if (out_setup(epoint_id, message_type, param, NULL, number))
+ return; // join destroyed
+ }
+ /* after keypad finish dialing */
+ break;
+ }
+ /* dialed number */
numbers = param->setup.dialinginfo.id;
while((number = strsep(&numbers, ","))) {
- if (out_setup(epoint_id, message_type, param, number))
+ if (out_setup(epoint_id, message_type, param, number, NULL))
return; // join destroyed
}
break;
}
- if (out_setup(epoint_id, message_type, param, NULL))
+ if (out_setup(epoint_id, message_type, param, param->setup.dialinginfo.id, param->setup.dialinginfo.keypad))
return; // join destroyed
break;
PDEBUG(DEBUG_JOIN, "no need to send a message because there is no other endpoint than the calling one.\n");
}
} else {
- PDEBUG(DEBUG_JOIN, "sending message ep%ld -> ep%ld.\n", epoint_id, relation->epoint_id);
- message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, message_type);
- memcpy(&message->param, param, sizeof(union parameter));
- message_put(message);
- PDEBUG(DEBUG_JOIN, "message sent.\n");
- }
-}
-
-
-/* join process is called from the main loop
- * it processes the current calling state.
- * returns 0 if join nothing was done
- */
-int JoinPBX::handler(void)
-{
-// struct join_relation *relation;
-// char dialing[32][32];
-// int port[32];
-// int found;
-// int i, j;
-// char *p;
-
- /* the bridge must be updated */
- if (j_updatebridge) {
- bridge();
- j_updatebridge = 0;
- return(1);
+ /* sending message to other relation(s) */
+ relation = j_relation;
+ while(relation) {
+ if (relation->epoint_id != epoint_id) {
+ PDEBUG(DEBUG_JOIN, "sending message ep%ld -> ep%ld.\n", epoint_id, relation->epoint_id);
+ message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, message_type);
+ memcpy(&message->param, param, sizeof(union parameter));
+ message_put(message);
+ PDEBUG(DEBUG_JOIN, "message sent.\n");
+ }
+ relation = relation->next;
+ }
}
-
- return(0);
}
* if other outgoing endpoints already exists, they are release as well.
* note: if this functions fails, it will destroy its own join object!
*/
-int JoinPBX::out_setup(unsigned int epoint_id, int message_type, union parameter *param, char *newnumber)
+int JoinPBX::out_setup(unsigned int epoint_id, int message_type, union parameter *param, char *newnumber, char *newkeypad)
{
struct join_relation *relation;
struct lcr_msg *message;
memcpy(&message->param, param, sizeof(union parameter));
if (newnumber)
SCPY(message->param.setup.dialinginfo.id, newnumber);
- PDEBUG(DEBUG_JOIN, "setup message sent to ep %d with number='%s'.\n", relation->epoint_id, message->param.setup.dialinginfo.id);
+ else
+ message->param.setup.dialinginfo.id[0] = '\0';
+ if (newkeypad)
+ SCPY(message->param.setup.dialinginfo.keypad, newkeypad);
+ else
+ message->param.setup.dialinginfo.keypad[0] = '\0';
+ PDEBUG(DEBUG_JOIN, "setup message sent to ep %d with number='%s' keypad='%s'.\n", relation->epoint_id, message->param.setup.dialinginfo.id, message->param.setup.dialinginfo.keypad);
message_put(message);
return(0);
}