Added keypad forwarding, keypad parameter, chan_lcr keypad option 'k'.
[lcr.git] / joinpbx.cpp
index 5c686dc..d21daf3 100644 (file)
@@ -525,7 +525,7 @@ int joinpbx_countrelations(unsigned int join_id)
        if (!join)
                return(0);
 
        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(2);
 
        if (join->j_type != JOIN_TYPE_PBX)
@@ -542,6 +542,31 @@ int joinpbx_countrelations(unsigned int join_id)
        return(i);
 }
 
        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;
 void JoinPBX::remove_relation(struct join_relation *relation)
 {
        struct join_relation *temp, **tempp;
@@ -635,6 +660,9 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par
                return;
        }
 
                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;
        /* process party line */
        if (message_type == MESSAGE_SETUP) if (param->setup.partyline && !j_partyline) {
                j_partyline = param->setup.partyline;
@@ -783,7 +811,12 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par
                                release(j_relation, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
                                return; // must return, because join IS destroyed
                        }
                                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) {
                        release_again2:
                        reltemp = j_relation;
                        while(reltemp) {
@@ -809,34 +842,30 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par
                return; // must return, because join may be destroyed
        }
 
                return; // must return, because join may be destroyed
        }
 
-       /* count relations */
-       num=joinpbx_countrelations(j_serial);
-
        /* check number of relations */
        /* 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;
        }
 
                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) {
                                numbers = param->setup.dialinginfo.id;
                                while((number = strsep(&numbers, ","))) {
                switch(message_type) {
                        case MESSAGE_SETUP:
                        if (param->setup.dialinginfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
                                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
+                               }
+                               numbers = param->setup.dialinginfo.id;
+                               while((number = strsep(&numbers, ","))) {
+                                       if (out_setup(epoint_id, message_type, param, NULL, number))
                                                return; // join destroyed
                                }
                                break;
                        }
                                                return; // join destroyed
                                }
                                break;
                        }
-                       if (out_setup(epoint_id, message_type, param, NULL))
+                       if (out_setup(epoint_id, message_type, param, NULL, NULL))
                                return; // join destroyed
                        break;
 
                                return; // join destroyed
                        break;
 
@@ -844,11 +873,18 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par
                        PDEBUG(DEBUG_JOIN, "no need to send a message because there is no other endpoint than the calling one.\n");
                }
        } else {
                        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");
+               /* 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;
+               }
        }
 }
 
        }
 }
 
@@ -914,7 +950,7 @@ int track_notify(int oldstate, int notify)
  * if other outgoing endpoints already exists, they are release as well.
  * note: if this functions fails, it will destroy its own join object!
  */
  * 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;
 {
        struct join_relation *relation;
        struct lcr_msg *message;
@@ -943,7 +979,9 @@ int JoinPBX::out_setup(unsigned int epoint_id, int message_type, union parameter
        memcpy(&message->param, param, sizeof(union parameter));
        if (newnumber)
                SCPY(message->param.setup.dialinginfo.id, newnumber);
        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);
+       if (newkeypad)
+               SCPY(message->param.setup.dialinginfo.keypad, newkeypad);
+       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);
 }
        message_put(message);
        return(0);
 }