1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
10 \*****************************************************************************/
17 #include <sys/types.h>
21 #define __u8 unsigned char
22 #define __u16 unsigned short
23 #define __u32 unsigned long
24 #include "linux/isdnif.h"
27 /* notify endpoint about state change (if any) */
28 static int notify_state_change(int join_id, int epoint_id, int old_state, int new_state)
30 int notify_off = 0, notify_on = 0;
31 struct message *message;
33 if (old_state == new_state)
38 case NOTIFY_STATE_ACTIVE:
41 case NOTIFY_STATE_HOLD:
42 notify_on = INFO_NOTIFY_REMOTE_HOLD;
44 case NOTIFY_STATE_SUSPEND:
45 notify_on = INFO_NOTIFY_USER_SUSPENDED;
47 case NOTIFY_STATE_CONFERENCE:
48 notify_on = INFO_NOTIFY_CONFERENCE_ESTABLISHED;
53 case NOTIFY_STATE_HOLD:
56 case NOTIFY_STATE_ACTIVE:
57 notify_off = INFO_NOTIFY_REMOTE_RETRIEVAL;
59 case NOTIFY_STATE_SUSPEND:
60 notify_off = INFO_NOTIFY_REMOTE_RETRIEVAL;
61 notify_on = INFO_NOTIFY_USER_SUSPENDED;
63 case NOTIFY_STATE_CONFERENCE:
64 notify_off = INFO_NOTIFY_REMOTE_RETRIEVAL;
65 notify_on = INFO_NOTIFY_CONFERENCE_ESTABLISHED;
70 case NOTIFY_STATE_SUSPEND:
73 case NOTIFY_STATE_ACTIVE:
74 notify_off = INFO_NOTIFY_USER_RESUMED;
76 case NOTIFY_STATE_HOLD:
77 notify_off = INFO_NOTIFY_USER_RESUMED;
78 notify_on = INFO_NOTIFY_REMOTE_HOLD;
80 case NOTIFY_STATE_CONFERENCE:
81 notify_off = INFO_NOTIFY_USER_RESUMED;
82 notify_on = INFO_NOTIFY_CONFERENCE_ESTABLISHED;
87 case NOTIFY_STATE_CONFERENCE:
90 case NOTIFY_STATE_ACTIVE:
91 notify_off = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
93 case NOTIFY_STATE_HOLD:
94 notify_off = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
95 notify_on = INFO_NOTIFY_REMOTE_HOLD;
97 case NOTIFY_STATE_SUSPEND:
98 notify_off = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
99 notify_on = INFO_NOTIFY_USER_SUSPENDED;
105 if (join_id && notify_off)
107 message = message_create(join_id, epoint_id, JOIN_TO_EPOINT, MESSAGE_NOTIFY);
108 message->param.notifyinfo.notify = notify_off;
109 message_put(message);
112 if (join_id && notify_on)
114 message = message_create(join_id, epoint_id, JOIN_TO_EPOINT, MESSAGE_NOTIFY);
115 message->param.notifyinfo.notify = notify_on;
116 message_put(message);
123 /* debug function for join */
124 void joinpbx_debug(class JoinPBX *joinpbx, char *function)
126 struct join_relation *relation;
127 struct port_list *portlist;
128 class Endpoint *epoint;
132 if (!(options.deb & DEBUG_JOIN))
135 PDEBUG(DEBUG_JOIN, "join(%d) start (called from %s)\n", joinpbx->j_serial, function);
137 relation = joinpbx->j_relation;
140 PDEBUG(DEBUG_JOIN, "join has no relations\n");
143 epoint = find_epoint_id(relation->epoint_id);
146 PDEBUG(DEBUG_JOIN, "warning: relations epoint id=%ld doesn't exists!\n", relation->epoint_id);
147 relation = relation->next;
151 UPRINT(strchr(buffer,0), "*** ep%ld", relation->epoint_id);
152 UPRINT(strchr(buffer,0), " ifs=");
153 portlist = epoint->ep_portlist;
156 port = find_port_id(portlist->port_id);
158 UPRINT(strchr(buffer,0), "%s,", port->p_name);
160 UPRINT(strchr(buffer,0), "<port %ld doesn't exist>,", portlist->port_id);
161 portlist = portlist->next;
163 // 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");
164 UPRINT(strchr(buffer,0), " endpoint=%d on=%s", epoint->ep_serial, (epoint->ep_join_id==joinpbx->j_serial)?"yes":"no");
165 switch(relation->type)
167 case RELATION_TYPE_CALLING:
168 UPRINT(strchr(buffer,0), " type=CALLING");
170 case RELATION_TYPE_SETUP:
171 UPRINT(strchr(buffer,0), " type=SETUP");
173 case RELATION_TYPE_CONNECT:
174 UPRINT(strchr(buffer,0), " type=CONNECT");
177 UPRINT(strchr(buffer,0), " type=unknown");
180 switch(relation->channel_state)
182 case CHANNEL_STATE_CONNECT:
183 UPRINT(strchr(buffer,0), " channel=CONNECT");
185 case CHANNEL_STATE_HOLD:
186 UPRINT(strchr(buffer,0), " channel=HOLD");
189 UPRINT(strchr(buffer,0), " channel=unknown");
192 switch(relation->tx_state)
194 case NOTIFY_STATE_ACTIVE:
195 UPRINT(strchr(buffer,0), " tx_state=ACTIVE");
197 case NOTIFY_STATE_HOLD:
198 UPRINT(strchr(buffer,0), " tx_state=HOLD");
200 case NOTIFY_STATE_SUSPEND:
201 UPRINT(strchr(buffer,0), " tx_state=SUSPEND");
203 case NOTIFY_STATE_CONFERENCE:
204 UPRINT(strchr(buffer,0), " tx_state=CONFERENCE");
207 UPRINT(strchr(buffer,0), " tx_state=unknown");
210 switch(relation->rx_state)
212 case NOTIFY_STATE_ACTIVE:
213 UPRINT(strchr(buffer,0), " rx_state=ACTIVE");
215 case NOTIFY_STATE_HOLD:
216 UPRINT(strchr(buffer,0), " rx_state=HOLD");
218 case NOTIFY_STATE_SUSPEND:
219 UPRINT(strchr(buffer,0), " rx_state=SUSPEND");
221 case NOTIFY_STATE_CONFERENCE:
222 UPRINT(strchr(buffer,0), " rx_state=CONFERENCE");
225 UPRINT(strchr(buffer,0), " rx_state=unknown");
228 PDEBUG(DEBUG_JOIN, "%s\n", buffer);
229 relation = relation->next;
232 PDEBUG(DEBUG_JOIN, "end\n");
237 * constructor for a new join
238 * the join will have a relation to the calling endpoint
240 JoinPBX::JoinPBX(class Endpoint *epoint) : Join()
242 struct join_relation *relation;
243 // char filename[256];
246 FATAL("epoint is NULL.\n");
248 PDEBUG(DEBUG_JOIN, "creating new join and connecting it to the endpoint.\n");
250 j_type = JOIN_TYPE_PBX;
252 j_caller_id[0] = '\0';
258 j_partyline_jingle = 0;
262 /* initialize a relation only to the calling interface */
263 relation = j_relation = (struct join_relation *)MALLOC(sizeof(struct join_relation));
265 relation->type = RELATION_TYPE_CALLING;
266 relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new join */
267 relation->tx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
268 relation->rx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
269 relation->epoint_id = epoint->ep_serial;
272 if (options.deb & DEBUG_JOIN)
273 joinpbx_debug(this, "JoinPBX::Constructor(new join)");
282 struct join_relation *relation, *rtemp;
284 relation = j_relation;
287 rtemp = relation->next;
288 FREE(relation, sizeof(struct join_relation));
295 /* bridge sets the audio flow of all bchannels assiociated to 'this' join
296 * also it changes and notifies active/hold/conference states
298 void JoinPBX::bridge(void)
300 struct join_relation *relation;
301 struct message *message;
302 int numconnect = 0, relations = 0;
303 class Endpoint *epoint;
304 struct port_list *portlist;
306 #ifdef DEBUG_COREBRIDGE
307 int allmISDN = 0; // never set for debug purpose
309 int allmISDN = 1; // set until a non-mISDN relation is found
312 relation = j_relation;
315 /* count all relations */
318 /* check for relation's objects */
319 epoint = find_epoint_id(relation->epoint_id);
322 PERROR("software error: relation without existing endpoints.\n");
323 relation = relation->next;
326 portlist = epoint->ep_portlist;
329 PDEBUG(DEBUG_JOIN, "join%d ignoring relation without port object.\n", j_serial);
330 //#warning testing: keep on hold until single audio stream available
331 relation->channel_state = CHANNEL_STATE_HOLD;
332 relation = relation->next;
337 PDEBUG(DEBUG_JOIN, "join%d ignoring relation with ep%d due to port_list.\n", j_serial, epoint->ep_serial);
338 //#warning testing: keep on hold until single audio stream available
339 relation->channel_state = CHANNEL_STATE_HOLD;
340 relation = relation->next;
343 port = find_port_id(portlist->port_id);
346 PDEBUG(DEBUG_JOIN, "join%d ignoring relation without existing port object.\n", j_serial);
347 relation = relation->next;
350 if ((port->p_type&PORT_CLASS_MASK)!=PORT_CLASS_mISDN)
352 PDEBUG(DEBUG_JOIN, "join%d ignoring relation ep%d because it's port is not mISDN.\n", j_serial, epoint->ep_serial);
355 PDEBUG(DEBUG_JOIN, "join%d not all endpoints are mISDN.\n", j_serial);
358 relation = relation->next;
362 relation = relation->next;
365 PDEBUG(DEBUG_JOIN, "join%d members=%d %s\n", j_serial, relations, (allmISDN)?"(all are mISDN-members)":"(not all are mISDN-members)");
366 /* we notify all relations about rxdata. */
367 relation = j_relation;
370 /* count connected relations */
371 if ((relation->channel_state == CHANNEL_STATE_CONNECT)
372 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
373 && (relation->rx_state != NOTIFY_STATE_HOLD))
376 /* remove unconnected parties from conference, also remove remotely disconnected parties so conference will not be disturbed. */
377 if (relation->channel_state == CHANNEL_STATE_CONNECT
378 && relation->rx_state != NOTIFY_STATE_HOLD
379 && relation->rx_state != NOTIFY_STATE_SUSPEND
380 && relations>1 // no conf with one member
381 && allmISDN) // no conf if any member is not mISDN
383 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL);
384 message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
385 message->param.mISDNsignal.conf = j_serial<<16 | j_pid;
386 PDEBUG(DEBUG_JOIN, "join%d EP%d +on+ id: 0x%08x\n", j_serial, relation->epoint_id, message->param.mISDNsignal.conf);
387 message_put(message);
390 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL);
391 message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
392 message->param.mISDNsignal.conf = 0;
393 PDEBUG(DEBUG_JOIN, "join%d EP%d +off+ id: 0x%08x\n", j_serial, relation->epoint_id, message->param.mISDNsignal.conf);
394 message_put(message);
398 * request data from endpoint/port if:
400 * - any without mISDN
401 * in this case we bridge
403 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL);
404 message->param.mISDNsignal.message = mISDNSIGNAL_JOINDATA;
405 message->param.mISDNsignal.joindata = (relations==2 && !allmISDN);
406 PDEBUG(DEBUG_JOIN, "join%d EP%d set joindata=%d\n", j_serial, relation->epoint_id, message->param.mISDNsignal.joindata);
407 message_put(message);
409 relation = relation->next;
412 /* two people just exchange their states */
413 if (relations==2 && !j_partyline)
415 PDEBUG(DEBUG_JOIN, "join%d 2 relations / no partyline\n", j_serial);
416 relation = j_relation;
417 relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, relation->next->rx_state);
418 relation->next->tx_state = notify_state_change(j_serial, relation->next->epoint_id, relation->next->tx_state, relation->rx_state);
420 /* one member in a join, so we put her on hold */
421 if ((relations==1 || numconnect==1)/* && !j_partyline_jingle*/)
423 PDEBUG(DEBUG_JOIN, "join%d 1 member or only 1 connected, put on hold\n");
424 relation = j_relation;
427 if ((relation->channel_state == CHANNEL_STATE_CONNECT)
428 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
429 && (relation->rx_state != NOTIFY_STATE_HOLD))
430 relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_HOLD);
431 relation = relation->next;
434 /* if conference/partyline (or more than two members and more than one is connected), so we set conference state */
436 PDEBUG(DEBUG_JOIN, "join%d %d members, %d connected, signal conference\n", relations, numconnect);
437 relation = j_relation;
440 if ((relation->channel_state == CHANNEL_STATE_CONNECT)
441 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
442 && (relation->rx_state != NOTIFY_STATE_HOLD))
443 relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_CONFERENCE);
444 relation = relation->next;
450 * bridging is only possible with two connected endpoints
452 void JoinPBX::bridge_data(unsigned long epoint_from, struct join_relation *relation_from, union parameter *param)
454 struct join_relation *relation_to;
456 /* if we are alone */
457 if (!j_relation->next)
460 /* if we are more than two */
461 if (j_relation->next->next)
464 /* skip if source endpoint has NOT audio mode CONNECT */
465 if (relation_from->channel_state != CHANNEL_STATE_CONNECT)
468 /* get destination relation */
469 relation_to = j_relation;
470 if (relation_to == relation_from)
472 /* oops, we are the first, so destination is: */
473 relation_to = relation_to->next;
476 /* skip if destination endpoint has NOT audio mode CONNECT */
477 if (relation_to->channel_state != CHANNEL_STATE_CONNECT)
480 /* now we may send our data to the endpoint where it
481 * will be delivered to the port
483 //printf("from %d, to %d\n", relation_from->epoint_id, relation_to->epoint_id);
484 message_forward(j_serial, relation_to->epoint_id, JOIN_TO_EPOINT, param);
487 /* release join from endpoint
488 * if the join has two relations, all relations are freed and the join will be
490 * on outgoing relations, the cause is collected, if not connected
491 * returns if join has been destroyed
493 int JoinPBX::release(struct join_relation *relation, int location, int cause)
495 struct join_relation *reltemp, **relationpointer;
496 struct message *message;
500 /* remove from bridge */
501 if (relation->channel_state != CHANNEL_STATE_HOLD)
503 relation->channel_state = CHANNEL_STATE_HOLD;
504 j_updatebridge = 1; /* update bridge flag */
505 // note: if join is not released, bridge must be updated
508 /* detach given interface */
509 reltemp = j_relation;
510 relationpointer = &j_relation;
513 /* endpoint of function call */
514 if (relation == reltemp)
516 relationpointer = &reltemp->next;
517 reltemp = reltemp->next;
520 FATAL("relation not in list of our relations. this must not happen.\n");
521 //printf("releasing relation %d\n", reltemp->epoint_id);
522 *relationpointer = reltemp->next;
523 FREE(reltemp, sizeof(struct join_relation));
525 relation = reltemp = NULL; // just in case of reuse fault;
527 /* if no more relation */
530 PDEBUG(DEBUG_JOIN, "join is completely removed.\n");
531 /* there is no more endpoint related to the join */
534 // end of join object!
535 PDEBUG(DEBUG_JOIN, "join completely removed!\n");
537 /* if join is a party line */
540 PDEBUG(DEBUG_JOIN, "join is a conference room, so we keep it alive until the last party left.\n");
542 /* if only one relation left */
543 if (!j_relation->next)
545 PDEBUG(DEBUG_JOIN, "join has one relation left, so we send it a release with the given cause %d.\n", cause);
546 message = message_create(j_serial, j_relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE);
547 message->param.disconnectinfo.cause = cause;
548 message->param.disconnectinfo.location = location;
549 message_put(message);
552 // end of join object!
553 PDEBUG(DEBUG_JOIN, "join completely removed!\n");
559 if (options.deb & DEBUG_JOIN && join->j_type==JOIN_TYPE_PBX)
560 joinpbx_debug((class JoinPBX *)join, "join_release{all joins left}");
563 PDEBUG(DEBUG_JOIN, "join_release(): ended.\n");
567 /* count number of relations in a join
569 int joinpbx_countrelations(unsigned long join_id)
571 struct join_relation *relation;
574 class JoinPBX *joinpbx;
576 join = find_join_id(join_id);
581 if (join->j_type != JOIN_TYPE_REMOTE)
584 if (join->j_type != JOIN_TYPE_PBX)
586 joinpbx = (class JoinPBX *)join;
589 relation = joinpbx->j_relation;
593 relation = relation->next;
599 void JoinPBX::remove_relation(struct join_relation *relation)
601 struct join_relation *temp, **tempp;
610 if (temp == relation)
617 PERROR("relation not in join.\n");
621 PDEBUG(DEBUG_JOIN, "removing relation.\n");
622 *tempp = relation->next;
623 FREE(temp, sizeof(struct join_relation));
628 struct join_relation *JoinPBX::add_relation(void)
630 struct join_relation *relation;
634 PERROR("there is no first relation to this join\n");
637 relation = j_relation;
638 while(relation->next)
639 relation = relation->next;
641 relation->next = (struct join_relation *)MALLOC(sizeof(struct join_relation));
643 /* the record pointer is set at the first time the data is received for the relation */
645 // if (options.deb & DEBUG_JOIN)
646 // joinpbx_debug(join, "add_relation");
647 return(relation->next);
650 /* epoint sends a message to a join
653 void JoinPBX::message_epoint(unsigned long epoint_id, int message_type, union parameter *param)
656 struct join_relation *relation, *reltemp;
659 struct message *message;
660 // int size, writesize, oldpointer;
661 char *number, *numbers;
665 PERROR("software error, epoint == NULL\n");
669 // if (options.deb & DEBUG_JOIN)
671 // PDEBUG(DEBUG_JOIN, "message %d received from ep%d.\n", message, epoint->ep_serial);
672 // joinpbx_debug(join,"Join::message_epoint");
674 if (options.deb & DEBUG_JOIN)
676 if (message_type != MESSAGE_DATA)
681 if (cl->j_type == JOIN_TYPE_PBX)
682 joinpbx_debug((class JoinPBX *)cl, "Join::message_epoint{all joins before processing}");
689 relation = j_relation;
692 if (relation->epoint_id == epoint_id)
694 relation = relation->next;
698 PDEBUG(DEBUG_JOIN, "no relation back to the endpoint found, ignoring (join=%d, endpoint=%d)\n", j_serial, epoint_id);
702 /* process party line */
703 if (message_type == MESSAGE_SETUP) if (param->setup.partyline && !j_partyline)
705 j_partyline = param->setup.partyline;
706 j_partyline_jingle = param->setup.partyline_jingle;
713 PDEBUG(DEBUG_JOIN, "respsone with connect in partyline mode.\n");
714 relation->type = RELATION_TYPE_CONNECT;
715 message = message_create(j_serial, epoint_id, JOIN_TO_EPOINT, MESSAGE_CONNECT);
716 SPRINT(message->param.connectinfo.id, "%d", j_partyline);
717 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
718 message_put(message);
719 j_updatebridge = 1; /* update bridge flag */
720 if (j_partyline_jingle)
724 case MESSAGE_AUDIOPATH:
725 PDEBUG(DEBUG_JOIN, "join received channel message: %d.\n", param->audiopath);
726 if (relation->channel_state != param->audiopath)
728 relation->channel_state = param->audiopath;
729 j_updatebridge = 1; /* update bridge flag */
730 if (options.deb & DEBUG_JOIN)
731 joinpbx_debug(this, "Join::message_epoint{after setting new channel state}");
735 case MESSAGE_DISCONNECT:
736 PDEBUG(DEBUG_JOIN, "releasing after receiving disconnect, because join in partyline mode.\n");
737 message = message_create(j_serial, epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE);
738 message->param.disconnectinfo.cause = CAUSE_NORMAL;
739 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
740 message_put(message);
743 case MESSAGE_RELEASE:
744 PDEBUG(DEBUG_JOIN, "releasing from join\n");
745 release(relation, 0, 0);
746 if (j_relation && j_partyline_jingle)
751 PDEBUG(DEBUG_JOIN, "ignoring message, because join in partyline mode.\n");
757 /* process messages */
760 /* process audio path message */
761 case MESSAGE_AUDIOPATH:
762 PDEBUG(DEBUG_JOIN, "join received channel message: %d.\n", param->audiopath);
763 if (relation->channel_state != param->audiopath)
765 relation->channel_state = param->audiopath;
766 j_updatebridge = 1; /* update bridge flag */
767 if (options.deb & DEBUG_JOIN)
768 joinpbx_debug(this, "Join::message_epoint{after setting new channel state}");
774 switch(param->notifyinfo.notify)
776 case INFO_NOTIFY_USER_SUSPENDED:
777 case INFO_NOTIFY_USER_RESUMED:
778 case INFO_NOTIFY_REMOTE_HOLD:
779 case INFO_NOTIFY_REMOTE_RETRIEVAL:
780 case INFO_NOTIFY_CONFERENCE_ESTABLISHED:
781 case INFO_NOTIFY_CONFERENCE_DISCONNECTED:
782 new_state = track_notify(relation->rx_state, param->notifyinfo.notify);
783 if (new_state != relation->rx_state)
785 relation->rx_state = new_state;
787 if (options.deb & DEBUG_JOIN)
788 joinpbx_debug(this, "Join::message_epoint{after setting new rx state}");
793 /* send notification to all other endpoints */
794 reltemp = j_relation;
797 if (reltemp->epoint_id!=epoint_id && reltemp->epoint_id)
799 message = message_create(j_serial, reltemp->epoint_id, JOIN_TO_EPOINT, MESSAGE_NOTIFY);
800 memcpy(&message->param, param, sizeof(union parameter));
801 message_put(message);
803 reltemp = reltemp->next;
810 /* now send audio data to the other endpoint */
811 bridge_data(epoint_id, relation, param);
814 /* relations sends a connect */
815 case MESSAGE_CONNECT:
816 /* outgoing setup type becomes connected */
817 if (relation->type == RELATION_TYPE_SETUP)
818 relation->type = RELATION_TYPE_CONNECT;
819 /* release other relations in setup state */
821 reltemp = j_relation;
824 //printf("connect, checking relation %d\n", reltemp->epoint_id);
825 if (reltemp->type == RELATION_TYPE_SETUP)
827 //printf("relation %d is of type setup, releasing\n", reltemp->epoint_id);
828 /* send release to endpoint */
829 message = message_create(j_serial, reltemp->epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE);
830 message->param.disconnectinfo.cause = CAUSE_NONSELECTED;
831 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
832 message_put(message);
834 if (release(reltemp, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL)) // dummy cause, should not be used, since calling and connected endpoint still exist afterwards.
835 return; // must return, because join IS destroyed
838 if (reltemp->type == RELATION_TYPE_CALLING)
839 reltemp->type = RELATION_TYPE_CONNECT;
840 reltemp = reltemp->next;
842 break; // continue with our message
844 /* release is sent by endpoint */
845 case MESSAGE_RELEASE:
846 switch(relation->type)
848 case RELATION_TYPE_SETUP: /* by called */
849 /* collect cause and send collected cause */
850 collect_cause(&j_multicause, &j_multilocation, param->disconnectinfo.cause, param->disconnectinfo.location);
852 release(relation, j_multilocation, j_multicause);
854 release(relation, LOCATION_PRIVATE_LOCAL, CAUSE_UNSPECIFIED);
857 case RELATION_TYPE_CALLING: /* by calling */
858 /* remove us, if we don't have a called releation yet */
859 if (!j_relation->next)
861 release(j_relation, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
862 return; // must return, because join IS destroyed
864 /* remove all relations that are in called */
866 reltemp = j_relation;
869 if (reltemp->type == RELATION_TYPE_SETUP)
871 /* send release to endpoint */
872 message = message_create(j_serial, reltemp->epoint_id, JOIN_TO_EPOINT, message_type);
873 memcpy(&message->param, param, sizeof(union parameter));
874 message_put(message);
876 if (release(reltemp, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL))
877 return; // must return, because join IS destroyed
880 reltemp = reltemp->next;
882 PERROR("we are still here, this should not happen\n");
885 default: /* by connected */
886 /* send current cause */
887 release(relation, param->disconnectinfo.location, param->disconnectinfo.cause);
889 return; // must return, because join may be destroyed
892 /* count relations */
893 num=joinpbx_countrelations(j_serial);
895 /* check number of relations */
898 PDEBUG(DEBUG_JOIN, "join has more than two relations so there is no need to send a message.\n");
902 /* find interfaces not related to calling epoint */
903 relation = j_relation;
906 if (relation->epoint_id != epoint_id)
908 relation = relation->next;
915 if (param->setup.dialinginfo.itype == INFO_ITYPE_ISDN_EXTENSION)
917 numbers = param->setup.dialinginfo.id;
918 while((number = strsep(&numbers, ",")))
920 if (out_setup(epoint_id, message_type, param, number))
921 return; // join destroyed
925 if (out_setup(epoint_id, message_type, param, NULL))
926 return; // join destroyed
930 PDEBUG(DEBUG_JOIN, "no need to send a message because there is no other endpoint than the calling one.\n");
934 PDEBUG(DEBUG_JOIN, "sending message ep%ld -> ep%ld.\n", epoint_id, relation->epoint_id);
935 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, message_type);
936 memcpy(&message->param, param, sizeof(union parameter));
937 message_put(message);
938 PDEBUG(DEBUG_JOIN, "message sent.\n");
943 /* join process is called from the main loop
944 * it processes the current calling state.
945 * returns 0 if join nothing was done
947 int JoinPBX::handler(void)
949 // struct join_relation *relation;
950 // char dialing[32][32];
956 /* the bridge must be updated */
968 int track_notify(int oldstate, int notify)
970 int newstate = oldstate;
974 case INFO_NOTIFY_USER_RESUMED:
975 case INFO_NOTIFY_REMOTE_RETRIEVAL:
976 case INFO_NOTIFY_CONFERENCE_DISCONNECTED:
977 case INFO_NOTIFY_RESERVED_CT_1:
978 case INFO_NOTIFY_RESERVED_CT_2:
979 case INFO_NOTIFY_CALL_IS_DIVERTING:
980 newstate = NOTIFY_STATE_ACTIVE;
983 case INFO_NOTIFY_USER_SUSPENDED:
984 newstate = NOTIFY_STATE_SUSPEND;
987 case INFO_NOTIFY_REMOTE_HOLD:
988 newstate = NOTIFY_STATE_HOLD;
991 case INFO_NOTIFY_CONFERENCE_ESTABLISHED:
992 newstate = NOTIFY_STATE_CONFERENCE;
1001 * setup to exactly one endpoint
1002 * if it fails, the calling endpoint is released.
1003 * if other outgoing endpoints already exists, they are release as well.
1004 * note: if this functions fails, it will destroy its own join object!
1006 int JoinPBX::out_setup(unsigned long epoint_id, int message_type, union parameter *param, char *newnumber)
1008 struct join_relation *relation;
1009 struct message *message;
1010 class Endpoint *epoint;
1012 PDEBUG(DEBUG_JOIN, "no endpoint found, so we will create an endpoint and send the setup message we have.\n");
1013 /* create a new relation */
1014 if (!(relation=add_relation()))
1015 FATAL("No memory for relation.\n");
1016 relation->type = RELATION_TYPE_SETUP;
1017 relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new join */
1018 relation->tx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
1019 relation->rx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
1020 /* create a new endpoint */
1021 epoint = new Endpoint(0, j_serial);
1023 FATAL("No memory for Endpoint instance\n");
1024 if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 1))) // outgoing
1025 FATAL("No memory for Endpoint Application instance\n");
1026 relation->epoint_id = epoint->ep_serial;
1027 /* send setup message to new endpoint */
1028 //printf("JOLLY DEBUG: %d\n",join_countrelations(j_serial));
1029 //i if (options.deb & DEBUG_JOIN)
1030 // joinpbx_debug(join, "Join::message_epoint");
1031 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, message_type);
1032 memcpy(&message->param, param, sizeof(union parameter));
1034 SCPY(message->param.setup.dialinginfo.id, newnumber);
1035 PDEBUG(DEBUG_JOIN, "setup message sent to ep %d with number='%s'.\n", relation->epoint_id, message->param.setup.dialinginfo.id);
1036 message_put(message);
1041 /* send play message to all members to play join/release jingle */
1042 void JoinPBX::play_jingle(int in)
1044 struct join_relation *relation;
1045 struct message *message;
1047 relation = j_relation;
1051 if (!relation->next)
1056 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_TONE);
1057 SCPY(message->param.tone.name, (char *)((in)?"left":"joined"));
1058 message_put(message);
1059 relation = relation->next;