1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
10 \*****************************************************************************/
13 //#define __u8 unsigned char
14 //#define __u16 unsigned short
15 //#define __u32 unsigned int
18 /* notify endpoint about state change (if any) */
19 static int notify_state_change(int join_id, int epoint_id, int old_state, int new_state)
21 int notify_off = 0, notify_on = 0;
22 struct lcr_msg *message;
24 if (old_state == new_state)
29 case NOTIFY_STATE_ACTIVE:
32 case NOTIFY_STATE_HOLD:
33 notify_on = INFO_NOTIFY_REMOTE_HOLD;
35 case NOTIFY_STATE_SUSPEND:
36 notify_on = INFO_NOTIFY_USER_SUSPENDED;
38 case NOTIFY_STATE_CONFERENCE:
39 notify_on = INFO_NOTIFY_CONFERENCE_ESTABLISHED;
44 case NOTIFY_STATE_HOLD:
47 case NOTIFY_STATE_ACTIVE:
48 notify_off = INFO_NOTIFY_REMOTE_RETRIEVAL;
50 case NOTIFY_STATE_SUSPEND:
51 notify_off = INFO_NOTIFY_REMOTE_RETRIEVAL;
52 notify_on = INFO_NOTIFY_USER_SUSPENDED;
54 case NOTIFY_STATE_CONFERENCE:
55 notify_off = INFO_NOTIFY_REMOTE_RETRIEVAL;
56 notify_on = INFO_NOTIFY_CONFERENCE_ESTABLISHED;
61 case NOTIFY_STATE_SUSPEND:
64 case NOTIFY_STATE_ACTIVE:
65 notify_off = INFO_NOTIFY_USER_RESUMED;
67 case NOTIFY_STATE_HOLD:
68 notify_off = INFO_NOTIFY_USER_RESUMED;
69 notify_on = INFO_NOTIFY_REMOTE_HOLD;
71 case NOTIFY_STATE_CONFERENCE:
72 notify_off = INFO_NOTIFY_USER_RESUMED;
73 notify_on = INFO_NOTIFY_CONFERENCE_ESTABLISHED;
78 case NOTIFY_STATE_CONFERENCE:
81 case NOTIFY_STATE_ACTIVE:
82 notify_off = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
84 case NOTIFY_STATE_HOLD:
85 notify_off = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
86 notify_on = INFO_NOTIFY_REMOTE_HOLD;
88 case NOTIFY_STATE_SUSPEND:
89 notify_off = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
90 notify_on = INFO_NOTIFY_USER_SUSPENDED;
96 if (join_id && notify_off)
98 message = message_create(join_id, epoint_id, JOIN_TO_EPOINT, MESSAGE_NOTIFY);
99 message->param.notifyinfo.notify = notify_off;
100 message_put(message);
103 if (join_id && notify_on)
105 message = message_create(join_id, epoint_id, JOIN_TO_EPOINT, MESSAGE_NOTIFY);
106 message->param.notifyinfo.notify = notify_on;
107 message_put(message);
114 /* debug function for join */
115 void joinpbx_debug(class JoinPBX *joinpbx, const char *function)
117 struct join_relation *relation;
118 struct port_list *portlist;
119 class Endpoint *epoint;
123 if (!(options.deb & DEBUG_JOIN))
126 PDEBUG(DEBUG_JOIN, "join(%d) start (called from %s)\n", joinpbx->j_serial, function);
128 relation = joinpbx->j_relation;
131 PDEBUG(DEBUG_JOIN, "join has no relations\n");
134 epoint = find_epoint_id(relation->epoint_id);
137 PDEBUG(DEBUG_JOIN, "warning: relations epoint id=%d doesn't exists!\n", relation->epoint_id);
138 relation = relation->next;
142 UPRINT(strchr(buffer,0), "*** ep%d", relation->epoint_id);
143 UPRINT(strchr(buffer,0), " ifs=");
144 portlist = epoint->ep_portlist;
147 port = find_port_id(portlist->port_id);
149 UPRINT(strchr(buffer,0), "%s,", port->p_name);
151 UPRINT(strchr(buffer,0), "<port %d doesn't exist>,", portlist->port_id);
152 portlist = portlist->next;
154 // UPRINT(strchr(buffer,0), " endpoint=%d on=%s hold=%s", epoint->ep_serial, (epoint->ep_join_id==joinpbx->j_serial)?"yes":"no", (epoint->get_hold_id()==joinpbx->j_serial)?"yes":"no");
155 UPRINT(strchr(buffer,0), " endpoint=%d on=%s", epoint->ep_serial, (epoint->ep_join_id==joinpbx->j_serial)?"yes":"no");
156 switch(relation->type)
158 case RELATION_TYPE_CALLING:
159 UPRINT(strchr(buffer,0), " type=CALLING");
161 case RELATION_TYPE_SETUP:
162 UPRINT(strchr(buffer,0), " type=SETUP");
164 case RELATION_TYPE_CONNECT:
165 UPRINT(strchr(buffer,0), " type=CONNECT");
168 UPRINT(strchr(buffer,0), " type=unknown");
171 if (relation->channel_state)
172 UPRINT(strchr(buffer,0), " channel=CONNECT");
174 UPRINT(strchr(buffer,0), " channel=HOLD");
175 switch(relation->tx_state)
177 case NOTIFY_STATE_ACTIVE:
178 UPRINT(strchr(buffer,0), " tx_state=ACTIVE");
180 case NOTIFY_STATE_HOLD:
181 UPRINT(strchr(buffer,0), " tx_state=HOLD");
183 case NOTIFY_STATE_SUSPEND:
184 UPRINT(strchr(buffer,0), " tx_state=SUSPEND");
186 case NOTIFY_STATE_CONFERENCE:
187 UPRINT(strchr(buffer,0), " tx_state=CONFERENCE");
190 UPRINT(strchr(buffer,0), " tx_state=unknown");
193 switch(relation->rx_state)
195 case NOTIFY_STATE_ACTIVE:
196 UPRINT(strchr(buffer,0), " rx_state=ACTIVE");
198 case NOTIFY_STATE_HOLD:
199 UPRINT(strchr(buffer,0), " rx_state=HOLD");
201 case NOTIFY_STATE_SUSPEND:
202 UPRINT(strchr(buffer,0), " rx_state=SUSPEND");
204 case NOTIFY_STATE_CONFERENCE:
205 UPRINT(strchr(buffer,0), " rx_state=CONFERENCE");
208 UPRINT(strchr(buffer,0), " rx_state=unknown");
211 PDEBUG(DEBUG_JOIN, "%s\n", buffer);
212 relation = relation->next;
215 PDEBUG(DEBUG_JOIN, "end\n");
220 * constructor for a new join
221 * the join will have a relation to the calling endpoint
223 JoinPBX::JoinPBX(class Endpoint *epoint) : Join()
225 struct join_relation *relation;
226 // char filename[256];
229 FATAL("epoint is NULL.\n");
231 PDEBUG(DEBUG_JOIN, "creating new join and connecting it to the endpoint.\n");
233 j_type = JOIN_TYPE_PBX;
235 j_caller_id[0] = '\0';
241 j_partyline_jingle = 0;
245 /* initialize a relation only to the calling interface */
246 relation = j_relation = (struct join_relation *)MALLOC(sizeof(struct join_relation));
248 relation->type = RELATION_TYPE_CALLING;
249 relation->channel_state = 0; /* audio is assumed on a new join */
250 relation->tx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
251 relation->rx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
252 relation->epoint_id = epoint->ep_serial;
255 if (options.deb & DEBUG_JOIN)
256 joinpbx_debug(this, "JoinPBX::Constructor(new join)");
265 struct join_relation *relation, *rtemp;
267 relation = j_relation;
270 rtemp = relation->next;
271 FREE(relation, sizeof(struct join_relation));
278 /* bridge sets the audio flow of all bchannels assiociated to 'this' join
279 * also it changes and notifies active/hold/conference states
281 void JoinPBX::bridge(void)
283 struct join_relation *relation;
284 struct lcr_msg *message;
285 int numconnect = 0, relations = 0;
286 class Endpoint *epoint;
287 struct port_list *portlist;
289 #ifdef DEBUG_COREBRIDGE
290 int allmISDN = 0; // never set for debug purpose
292 int allmISDN = 1; // set until a non-mISDN relation is found
295 relation = j_relation;
298 /* count all relations */
301 /* check for relation's objects */
302 epoint = find_epoint_id(relation->epoint_id);
305 PERROR("software error: relation without existing endpoints.\n");
306 relation = relation->next;
309 portlist = epoint->ep_portlist;
312 PDEBUG(DEBUG_JOIN, "join%d ignoring relation without port object.\n", j_serial);
313 //#warning testing: keep on hold until single audio stream available
314 relation->channel_state = 0;
315 relation = relation->next;
320 PDEBUG(DEBUG_JOIN, "join%d ignoring relation with ep%d due to port_list.\n", j_serial, epoint->ep_serial);
321 //#warning testing: keep on hold until single audio stream available
322 relation->channel_state = 0;
323 relation = relation->next;
326 port = find_port_id(portlist->port_id);
329 PDEBUG(DEBUG_JOIN, "join%d ignoring relation without existing port object.\n", j_serial);
330 relation = relation->next;
333 if ((port->p_type&PORT_CLASS_MASK)!=PORT_CLASS_mISDN)
335 PDEBUG(DEBUG_JOIN, "join%d ignoring relation ep%d because it's port is not mISDN.\n", j_serial, epoint->ep_serial);
338 PDEBUG(DEBUG_JOIN, "join%d not all endpoints are mISDN.\n", j_serial);
341 relation = relation->next;
345 relation = relation->next;
348 PDEBUG(DEBUG_JOIN, "join%d members=%d %s\n", j_serial, relations, (allmISDN)?"(all are mISDN-members)":"(not all are mISDN-members)");
349 /* we notify all relations about rxdata. */
350 relation = j_relation;
353 /* count connected relations */
354 if ((relation->channel_state == 1)
355 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
356 && (relation->rx_state != NOTIFY_STATE_HOLD))
359 /* remove unconnected parties from conference, also remove remotely disconnected parties so conference will not be disturbed. */
360 if (relation->channel_state == 1
361 && relation->rx_state != NOTIFY_STATE_HOLD
362 && relation->rx_state != NOTIFY_STATE_SUSPEND
363 && relations>1 // no conf with one member
364 && allmISDN) // no conf if any member is not mISDN
366 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL);
367 message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
368 message->param.mISDNsignal.conf = j_serial<<16 | j_pid;
369 PDEBUG(DEBUG_JOIN, "join%d EP%d +on+ id: 0x%08x\n", j_serial, relation->epoint_id, message->param.mISDNsignal.conf);
370 message_put(message);
373 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL);
374 message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
375 message->param.mISDNsignal.conf = 0;
376 PDEBUG(DEBUG_JOIN, "join%d EP%d +off+ id: 0x%08x\n", j_serial, relation->epoint_id, message->param.mISDNsignal.conf);
377 message_put(message);
381 * request data from endpoint/port if:
383 * - any without mISDN
384 * in this case we bridge
386 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL);
387 message->param.mISDNsignal.message = mISDNSIGNAL_JOINDATA;
388 message->param.mISDNsignal.joindata = (relations==2 && !allmISDN);
389 PDEBUG(DEBUG_JOIN, "join%d EP%d set joindata=%d\n", j_serial, relation->epoint_id, message->param.mISDNsignal.joindata);
390 message_put(message);
392 relation = relation->next;
395 /* two people just exchange their states */
396 if (relations==2 && !j_partyline)
398 PDEBUG(DEBUG_JOIN, "join%d 2 relations / no partyline\n", j_serial);
399 relation = j_relation;
400 relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, relation->next->rx_state);
401 relation->next->tx_state = notify_state_change(j_serial, relation->next->epoint_id, relation->next->tx_state, relation->rx_state);
403 /* one member in a join, so we put her on hold */
404 if ((relations==1 || numconnect==1)/* && !j_partyline_jingle*/)
406 PDEBUG(DEBUG_JOIN, "join%d 1 member or only 1 connected, put on hold\n", j_serial);
407 relation = j_relation;
410 if ((relation->channel_state == 1)
411 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
412 && (relation->rx_state != NOTIFY_STATE_HOLD))
413 relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_HOLD);
414 relation = relation->next;
417 /* if conference/partyline (or more than two members and more than one is connected), so we set conference state */
419 PDEBUG(DEBUG_JOIN, "join%d %d members, %d connected, signal conference\n", j_serial, relations, numconnect);
420 relation = j_relation;
423 if ((relation->channel_state == 1)
424 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
425 && (relation->rx_state != NOTIFY_STATE_HOLD))
426 relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_CONFERENCE);
427 relation = relation->next;
433 * bridging is only possible with two connected endpoints
435 void JoinPBX::bridge_data(unsigned int epoint_from, struct join_relation *relation_from, union parameter *param)
437 struct join_relation *relation_to;
439 /* if we are alone */
440 if (!j_relation->next)
443 /* if we are more than two */
444 if (j_relation->next->next)
447 /* skip if source endpoint has NOT audio mode CONNECT */
448 if (relation_from->channel_state != 1)
451 /* get destination relation */
452 relation_to = j_relation;
453 if (relation_to == relation_from)
455 /* oops, we are the first, so destination is: */
456 relation_to = relation_to->next;
459 /* skip if destination endpoint has NOT audio mode CONNECT */
460 if (relation_to->channel_state != 1)
463 /* now we may send our data to the endpoint where it
464 * will be delivered to the port
466 //printf("from %d, to %d\n", relation_from->epoint_id, relation_to->epoint_id);
467 message_forward(j_serial, relation_to->epoint_id, JOIN_TO_EPOINT, param);
470 /* release join from endpoint
471 * if the join has two relations, all relations are freed and the join will be
473 * on outgoing relations, the cause is collected, if not connected
474 * returns if join has been destroyed
476 int JoinPBX::release(struct join_relation *relation, int location, int cause)
478 struct join_relation *reltemp, **relationpointer;
479 struct lcr_msg *message;
483 /* remove from bridge */
484 if (relation->channel_state != 0)
486 relation->channel_state = 0;
487 j_updatebridge = 1; /* update bridge flag */
488 // note: if join is not released, bridge must be updated
491 /* detach given interface */
492 reltemp = j_relation;
493 relationpointer = &j_relation;
496 /* endpoint of function call */
497 if (relation == reltemp)
499 relationpointer = &reltemp->next;
500 reltemp = reltemp->next;
503 FATAL("relation not in list of our relations. this must not happen.\n");
504 //printf("releasing relation %d\n", reltemp->epoint_id);
505 *relationpointer = reltemp->next;
506 FREE(reltemp, sizeof(struct join_relation));
508 relation = reltemp = NULL; // just in case of reuse fault;
510 /* if no more relation */
513 PDEBUG(DEBUG_JOIN, "join is completely removed.\n");
514 /* there is no more endpoint related to the join */
517 // end of join object!
518 PDEBUG(DEBUG_JOIN, "join completely removed!\n");
520 /* if join is a party line */
523 PDEBUG(DEBUG_JOIN, "join is a conference room, so we keep it alive until the last party left.\n");
525 /* if only one relation left */
526 if (!j_relation->next)
528 PDEBUG(DEBUG_JOIN, "join has one relation left, so we send it a release with the given cause %d.\n", cause);
529 message = message_create(j_serial, j_relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE);
530 message->param.disconnectinfo.cause = cause;
531 message->param.disconnectinfo.location = location;
532 message_put(message);
535 // end of join object!
536 PDEBUG(DEBUG_JOIN, "join completely removed!\n");
542 if (options.deb & DEBUG_JOIN && join->j_type==JOIN_TYPE_PBX)
543 joinpbx_debug((class JoinPBX *)join, "join_release{all joins left}");
546 PDEBUG(DEBUG_JOIN, "join_release(): ended.\n");
550 /* count number of relations in a join
552 int joinpbx_countrelations(unsigned int join_id)
554 struct join_relation *relation;
557 class JoinPBX *joinpbx;
559 join = find_join_id(join_id);
564 if (join->j_type != JOIN_TYPE_REMOTE)
567 if (join->j_type != JOIN_TYPE_PBX)
569 joinpbx = (class JoinPBX *)join;
572 relation = joinpbx->j_relation;
576 relation = relation->next;
582 void JoinPBX::remove_relation(struct join_relation *relation)
584 struct join_relation *temp, **tempp;
593 if (temp == relation)
600 PERROR("relation not in join.\n");
604 PDEBUG(DEBUG_JOIN, "removing relation.\n");
605 *tempp = relation->next;
606 FREE(temp, sizeof(struct join_relation));
611 struct join_relation *JoinPBX::add_relation(void)
613 struct join_relation *relation;
617 PERROR("there is no first relation to this join\n");
620 relation = j_relation;
621 while(relation->next)
622 relation = relation->next;
624 relation->next = (struct join_relation *)MALLOC(sizeof(struct join_relation));
626 /* the record pointer is set at the first time the data is received for the relation */
628 // if (options.deb & DEBUG_JOIN)
629 // joinpbx_debug(join, "add_relation");
630 return(relation->next);
633 /* epoint sends a message to a join
636 void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union parameter *param)
639 struct join_relation *relation, *reltemp;
642 struct lcr_msg *message;
643 // int size, writesize, oldpointer;
644 char *number, *numbers;
648 PERROR("software error, epoint == NULL\n");
652 // if (options.deb & DEBUG_JOIN)
654 // PDEBUG(DEBUG_JOIN, "message %d received from ep%d.\n", message, epoint->ep_serial);
655 // joinpbx_debug(join,"Join::message_epoint");
657 if (options.deb & DEBUG_JOIN)
659 if (message_type != MESSAGE_DATA)
664 if (cl->j_type == JOIN_TYPE_PBX)
665 joinpbx_debug((class JoinPBX *)cl, "Join::message_epoint{all joins before processing}");
672 relation = j_relation;
675 if (relation->epoint_id == epoint_id)
677 relation = relation->next;
681 PDEBUG(DEBUG_JOIN, "no relation back to the endpoint found, ignoring (join=%d, endpoint=%d)\n", j_serial, epoint_id);
685 /* process party line */
686 if (message_type == MESSAGE_SETUP) if (param->setup.partyline && !j_partyline)
688 j_partyline = param->setup.partyline;
689 j_partyline_jingle = param->setup.partyline_jingle;
696 PDEBUG(DEBUG_JOIN, "respsone with connect in partyline mode.\n");
697 relation->type = RELATION_TYPE_CONNECT;
698 message = message_create(j_serial, epoint_id, JOIN_TO_EPOINT, MESSAGE_CONNECT);
699 SPRINT(message->param.connectinfo.id, "%d", j_partyline);
700 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
701 message_put(message);
702 j_updatebridge = 1; /* update bridge flag */
703 if (j_partyline_jingle)
707 case MESSAGE_AUDIOPATH:
708 PDEBUG(DEBUG_JOIN, "join received channel message: %d.\n", param->audiopath);
709 if (relation->channel_state != param->audiopath)
711 relation->channel_state = param->audiopath;
712 j_updatebridge = 1; /* update bridge flag */
713 if (options.deb & DEBUG_JOIN)
714 joinpbx_debug(this, "Join::message_epoint{after setting new channel state}");
718 case MESSAGE_DISCONNECT:
719 PDEBUG(DEBUG_JOIN, "releasing after receiving disconnect, because join in partyline mode.\n");
720 message = message_create(j_serial, epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE);
721 message->param.disconnectinfo.cause = CAUSE_NORMAL;
722 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
723 message_put(message);
726 case MESSAGE_RELEASE:
727 PDEBUG(DEBUG_JOIN, "releasing from join\n");
728 release(relation, 0, 0);
729 if (j_partyline_jingle)
734 PDEBUG(DEBUG_JOIN, "ignoring message, because join in partyline mode.\n");
740 /* process messages */
743 /* process audio path message */
744 case MESSAGE_AUDIOPATH:
745 PDEBUG(DEBUG_JOIN, "join received channel message: %d.\n", param->audiopath);
746 if (relation->channel_state != param->audiopath)
748 relation->channel_state = param->audiopath;
749 j_updatebridge = 1; /* update bridge flag */
750 if (options.deb & DEBUG_JOIN)
751 joinpbx_debug(this, "Join::message_epoint{after setting new channel state}");
757 switch(param->notifyinfo.notify)
759 case INFO_NOTIFY_USER_SUSPENDED:
760 case INFO_NOTIFY_USER_RESUMED:
761 case INFO_NOTIFY_REMOTE_HOLD:
762 case INFO_NOTIFY_REMOTE_RETRIEVAL:
763 case INFO_NOTIFY_CONFERENCE_ESTABLISHED:
764 case INFO_NOTIFY_CONFERENCE_DISCONNECTED:
765 new_state = track_notify(relation->rx_state, param->notifyinfo.notify);
766 if (new_state != relation->rx_state)
768 relation->rx_state = new_state;
770 if (options.deb & DEBUG_JOIN)
771 joinpbx_debug(this, "Join::message_epoint{after setting new rx state}");
776 /* send notification to all other endpoints */
777 reltemp = j_relation;
780 if (reltemp->epoint_id!=epoint_id && reltemp->epoint_id)
782 message = message_create(j_serial, reltemp->epoint_id, JOIN_TO_EPOINT, MESSAGE_NOTIFY);
783 memcpy(&message->param, param, sizeof(union parameter));
784 message_put(message);
786 reltemp = reltemp->next;
793 /* now send audio data to the other endpoint */
794 bridge_data(epoint_id, relation, param);
797 /* relations sends a connect */
798 case MESSAGE_CONNECT:
799 /* outgoing setup type becomes connected */
800 if (relation->type == RELATION_TYPE_SETUP)
801 relation->type = RELATION_TYPE_CONNECT;
802 /* release other relations in setup state */
804 reltemp = j_relation;
807 //printf("connect, checking relation %d\n", reltemp->epoint_id);
808 if (reltemp->type == RELATION_TYPE_SETUP)
810 //printf("relation %d is of type setup, releasing\n", reltemp->epoint_id);
811 /* send release to endpoint */
812 message = message_create(j_serial, reltemp->epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE);
813 message->param.disconnectinfo.cause = CAUSE_NONSELECTED;
814 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
815 message_put(message);
817 if (release(reltemp, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL)) // dummy cause, should not be used, since calling and connected endpoint still exist afterwards.
818 return; // must return, because join IS destroyed
821 if (reltemp->type == RELATION_TYPE_CALLING)
822 reltemp->type = RELATION_TYPE_CONNECT;
823 reltemp = reltemp->next;
825 break; // continue with our message
827 /* release is sent by endpoint */
828 case MESSAGE_RELEASE:
829 switch(relation->type)
831 case RELATION_TYPE_SETUP: /* by called */
832 /* collect cause and send collected cause */
833 collect_cause(&j_multicause, &j_multilocation, param->disconnectinfo.cause, param->disconnectinfo.location);
835 release(relation, j_multilocation, j_multicause);
837 release(relation, LOCATION_PRIVATE_LOCAL, CAUSE_UNSPECIFIED);
840 case RELATION_TYPE_CALLING: /* by calling */
841 /* remove us, if we don't have a called releation yet */
842 if (!j_relation->next)
844 release(j_relation, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
845 return; // must return, because join IS destroyed
847 /* remove all relations that are in called */
849 reltemp = j_relation;
852 if (reltemp->type == RELATION_TYPE_SETUP)
854 /* send release to endpoint */
855 message = message_create(j_serial, reltemp->epoint_id, JOIN_TO_EPOINT, message_type);
856 memcpy(&message->param, param, sizeof(union parameter));
857 message_put(message);
859 if (release(reltemp, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL))
860 return; // must return, because join IS destroyed
863 reltemp = reltemp->next;
865 PERROR("we are still here, this should not happen\n");
868 default: /* by connected */
869 /* send current cause */
870 release(relation, param->disconnectinfo.location, param->disconnectinfo.cause);
872 return; // must return, because join may be destroyed
875 /* count relations */
876 num=joinpbx_countrelations(j_serial);
878 /* check number of relations */
881 PDEBUG(DEBUG_JOIN, "join has more than two relations so there is no need to send a message.\n");
885 /* find interfaces not related to calling epoint */
886 relation = j_relation;
889 if (relation->epoint_id != epoint_id)
891 relation = relation->next;
898 if (param->setup.dialinginfo.itype == INFO_ITYPE_ISDN_EXTENSION)
900 numbers = param->setup.dialinginfo.id;
901 while((number = strsep(&numbers, ",")))
903 if (out_setup(epoint_id, message_type, param, number))
904 return; // join destroyed
908 if (out_setup(epoint_id, message_type, param, NULL))
909 return; // join destroyed
913 PDEBUG(DEBUG_JOIN, "no need to send a message because there is no other endpoint than the calling one.\n");
917 PDEBUG(DEBUG_JOIN, "sending message ep%ld -> ep%ld.\n", epoint_id, relation->epoint_id);
918 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, message_type);
919 memcpy(&message->param, param, sizeof(union parameter));
920 message_put(message);
921 PDEBUG(DEBUG_JOIN, "message sent.\n");
926 /* join process is called from the main loop
927 * it processes the current calling state.
928 * returns 0 if join nothing was done
930 int JoinPBX::handler(void)
932 // struct join_relation *relation;
933 // char dialing[32][32];
939 /* the bridge must be updated */
951 int track_notify(int oldstate, int notify)
953 int newstate = oldstate;
957 case INFO_NOTIFY_USER_RESUMED:
958 case INFO_NOTIFY_REMOTE_RETRIEVAL:
959 case INFO_NOTIFY_CONFERENCE_DISCONNECTED:
960 case INFO_NOTIFY_RESERVED_CT_1:
961 case INFO_NOTIFY_RESERVED_CT_2:
962 case INFO_NOTIFY_CALL_IS_DIVERTING:
963 newstate = NOTIFY_STATE_ACTIVE;
966 case INFO_NOTIFY_USER_SUSPENDED:
967 newstate = NOTIFY_STATE_SUSPEND;
970 case INFO_NOTIFY_REMOTE_HOLD:
971 newstate = NOTIFY_STATE_HOLD;
974 case INFO_NOTIFY_CONFERENCE_ESTABLISHED:
975 newstate = NOTIFY_STATE_CONFERENCE;
984 * setup to exactly one endpoint
985 * if it fails, the calling endpoint is released.
986 * if other outgoing endpoints already exists, they are release as well.
987 * note: if this functions fails, it will destroy its own join object!
989 int JoinPBX::out_setup(unsigned int epoint_id, int message_type, union parameter *param, char *newnumber)
991 struct join_relation *relation;
992 struct lcr_msg *message;
993 class Endpoint *epoint;
995 PDEBUG(DEBUG_JOIN, "no endpoint found, so we will create an endpoint and send the setup message we have.\n");
996 /* create a new relation */
997 if (!(relation=add_relation()))
998 FATAL("No memory for relation.\n");
999 relation->type = RELATION_TYPE_SETUP;
1000 relation->channel_state = 0; /* audio is assumed on a new join */
1001 relation->tx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
1002 relation->rx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
1003 /* create a new endpoint */
1004 epoint = new Endpoint(0, j_serial);
1006 FATAL("No memory for Endpoint instance\n");
1007 if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 1))) // outgoing
1008 FATAL("No memory for Endpoint Application instance\n");
1009 relation->epoint_id = epoint->ep_serial;
1010 /* send setup message to new endpoint */
1011 //printf("JOLLY DEBUG: %d\n",join_countrelations(j_serial));
1012 //i if (options.deb & DEBUG_JOIN)
1013 // joinpbx_debug(join, "Join::message_epoint");
1014 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, message_type);
1015 memcpy(&message->param, param, sizeof(union parameter));
1017 SCPY(message->param.setup.dialinginfo.id, newnumber);
1018 PDEBUG(DEBUG_JOIN, "setup message sent to ep %d with number='%s'.\n", relation->epoint_id, message->param.setup.dialinginfo.id);
1019 message_put(message);
1024 /* send play message to all members to play join/release jingle */
1025 void JoinPBX::play_jingle(int in)
1027 struct join_relation *relation;
1028 struct lcr_msg *message;
1030 relation = j_relation;
1034 if (!relation->next)
1038 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_TONE);
1039 SCPY(message->param.tone.name, (char *)((in)?"joined":"left"));
1040 message_put(message);
1041 relation = relation->next;