X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=joinpbx.cpp;h=4b0654013d49121edd05587601627a46c6d1c3d9;hp=dd54e9ba8e366d6e84781dc700f402a14ed16cd5;hb=97aa0881beacf536e3a2296381c055887583db8f;hpb=2188efe2cc9dfb473bf41540960382d7c43b892e diff --git a/joinpbx.cpp b/joinpbx.cpp index dd54e9b..4b06540 100644 --- a/joinpbx.cpp +++ b/joinpbx.cpp @@ -202,6 +202,7 @@ void joinpbx_debug(class JoinPBX *joinpbx, const char *function) PDEBUG(DEBUG_JOIN, "end\n"); } +int update_bridge(struct lcr_work *work, void *instance, int index); /* * constructor for a new join @@ -223,11 +224,12 @@ JoinPBX::JoinPBX(class Endpoint *epoint) : 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)); @@ -258,12 +260,23 @@ JoinPBX::~JoinPBX() 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; @@ -453,7 +466,7 @@ int JoinPBX::release(struct join_relation *relation, int location, int cause) /* 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 } @@ -542,6 +555,31 @@ int joinpbx_countrelations(unsigned int join_id) 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; @@ -652,7 +690,7 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par 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; @@ -661,7 +699,7 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par 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}"); } @@ -696,7 +734,7 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par 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}"); } @@ -714,7 +752,7 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par 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}"); } @@ -787,7 +825,7 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par return; // must return, because join IS destroyed } /* in a conf, we don't kill the other members */ - if (num > 2) { + if (num > 2 && !joinpbx_onecalling_othersetup(j_relation)) { release(relation, 0, 0); return; } @@ -818,30 +856,35 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par } /* 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; @@ -849,36 +892,19 @@ 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, "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); } @@ -919,7 +945,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! */ -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; @@ -948,7 +974,13 @@ 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); - 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); }