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';
261 /* initialize a relation only to the calling interface */
262 relation = j_relation = (struct join_relation *)MALLOC(sizeof(struct join_relation));
264 relation->type = RELATION_TYPE_CALLING;
265 relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new join */
266 relation->tx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
267 relation->rx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
268 relation->epoint_id = epoint->ep_serial;
271 if (options.deb & DEBUG_JOIN)
272 joinpbx_debug(this, "JoinPBX::Constructor(new join)");
281 struct join_relation *relation, *rtemp;
283 relation = j_relation;
286 rtemp = relation->next;
287 FREE(relation, sizeof(struct join_relation));
294 /* bridge sets the audio flow of all bchannels assiociated to 'this' join
295 * also it changes and notifies active/hold/conference states
297 void JoinPBX::bridge(void)
299 struct join_relation *relation;
300 struct message *message;
301 int numconnect = 0, relations = 0;
302 class Endpoint *epoint;
303 struct port_list *portlist;
305 #ifdef DEBUG_COREBRIDGE
306 int allmISDN = 0; // never set for debug purpose
308 int allmISDN = 1; // set until a non-mISDN relation is found
311 relation = j_relation;
314 /* count all relations */
317 /* check for relation's objects */
318 epoint = find_epoint_id(relation->epoint_id);
321 PERROR("software error: relation without existing endpoints.\n");
322 relation = relation->next;
325 portlist = epoint->ep_portlist;
328 PDEBUG(DEBUG_JOIN, "join%d ignoring relation without port object.\n", j_serial);
329 //#warning testing: keep on hold until single audio stream available
330 relation->channel_state = CHANNEL_STATE_HOLD;
331 relation = relation->next;
336 PDEBUG(DEBUG_JOIN, "join%d ignoring relation with ep%d due to port_list.\n", j_serial, epoint->ep_serial);
337 //#warning testing: keep on hold until single audio stream available
338 relation->channel_state = CHANNEL_STATE_HOLD;
339 relation = relation->next;
342 port = find_port_id(portlist->port_id);
345 PDEBUG(DEBUG_JOIN, "join%d ignoring relation without existing port object.\n", j_serial);
346 relation = relation->next;
349 if ((port->p_type&PORT_CLASS_MASK)!=PORT_CLASS_mISDN)
351 PDEBUG(DEBUG_JOIN, "join%d ignoring relation ep%d because it's port is not mISDN.\n", j_serial, epoint->ep_serial);
354 PDEBUG(DEBUG_JOIN, "join%d not all endpoints are mISDN.\n", j_serial);
357 relation = relation->next;
361 relation = relation->next;
364 PDEBUG(DEBUG_JOIN, "join%d members=%d %s\n", j_serial, relations, (allmISDN)?"(all are mISDN-members)":"(not all are mISDN-members)");
365 /* we notify all relations about rxdata. */
366 relation = j_relation;
369 /* count connected relations */
370 if ((relation->channel_state == CHANNEL_STATE_CONNECT)
371 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
372 && (relation->rx_state != NOTIFY_STATE_HOLD))
375 /* remove unconnected parties from conference, also remove remotely disconnected parties so conference will not be disturbed. */
376 if (relation->channel_state == CHANNEL_STATE_CONNECT
377 && relation->rx_state != NOTIFY_STATE_HOLD
378 && relation->rx_state != NOTIFY_STATE_SUSPEND
379 && relations>1 // no conf with one member
380 && allmISDN) // no conf if any member is not mISDN
382 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL);
383 message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
384 message->param.mISDNsignal.conf = j_serial<<16 | j_pid;
385 PDEBUG(DEBUG_JOIN, "join%d EP%d +on+ id: 0x%08x\n", j_serial, relation->epoint_id, message->param.mISDNsignal.conf);
386 message_put(message);
389 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL);
390 message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
391 message->param.mISDNsignal.conf = 0;
392 PDEBUG(DEBUG_JOIN, "join%d EP%d +off+ id: 0x%08x\n", j_serial, relation->epoint_id, message->param.mISDNsignal.conf);
393 message_put(message);
397 * request data from endpoint/port if:
399 * - any without mISDN
400 * in this case we bridge
402 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL);
403 message->param.mISDNsignal.message = mISDNSIGNAL_JOINDATA;
404 message->param.mISDNsignal.joindata = (relations==2 && !allmISDN);
405 PDEBUG(DEBUG_JOIN, "join%d EP%d set joindata=%d\n", j_serial, relation->epoint_id, message->param.mISDNsignal.joindata);
406 message_put(message);
408 relation = relation->next;
411 /* two people just exchange their states */
412 if (relations==2 && !j_partyline)
414 PDEBUG(DEBUG_JOIN, "join%d 2 relations / no partyline\n", j_serial);
415 relation = j_relation;
416 relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, relation->next->rx_state);
417 relation->next->tx_state = notify_state_change(j_serial, relation->next->epoint_id, relation->next->tx_state, relation->rx_state);
419 /* one member in a join, so we put her on hold */
420 if (relations==1 || numconnect==1)
422 PDEBUG(DEBUG_JOIN, "join%d 1 member or only 1 connected, put on hold\n");
423 relation = j_relation;
426 if ((relation->channel_state == CHANNEL_STATE_CONNECT)
427 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
428 && (relation->rx_state != NOTIFY_STATE_HOLD))
429 relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_HOLD);
430 relation = relation->next;
433 /* if conference/partyline or (more than two members and more than one is connected), so we set conference state */
435 PDEBUG(DEBUG_JOIN, "join%d %d members, %d connected, signal conference\n", relations, numconnect);
436 relation = j_relation;
439 if ((relation->channel_state == CHANNEL_STATE_CONNECT)
440 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
441 && (relation->rx_state != NOTIFY_STATE_HOLD))
442 relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_CONFERENCE);
443 relation = relation->next;
449 * bridging is only possible with two connected endpoints
451 void JoinPBX::bridge_data(unsigned long epoint_from, struct join_relation *relation_from, union parameter *param)
453 struct join_relation *relation_to;
455 /* if we are alone */
456 if (!j_relation->next)
459 /* if we are more than two */
460 if (j_relation->next->next)
463 /* skip if source endpoint has NOT audio mode CONNECT */
464 if (relation_from->channel_state != CHANNEL_STATE_CONNECT)
467 /* get destination relation */
468 relation_to = j_relation;
469 if (relation_to == relation_from)
471 /* oops, we are the first, so destination is: */
472 relation_to = relation_to->next;
475 /* skip if destination endpoint has NOT audio mode CONNECT */
476 if (relation_to->channel_state != CHANNEL_STATE_CONNECT)
479 /* now we may send our data to the endpoint where it
480 * will be delivered to the port
482 //printf("from %d, to %d\n", relation_from->epoint_id, relation_to->epoint_id);
483 message_forward(j_serial, relation_to->epoint_id, JOIN_TO_EPOINT, param);
486 /* release join from endpoint
487 * if the join has two relations, all relations are freed and the join will be
489 * on outgoing relations, the cause is collected, if not connected
490 * returns if join has been destroyed
492 int JoinPBX::release(struct join_relation *relation, int location, int cause)
494 struct join_relation *reltemp, **relationpointer;
495 struct message *message;
499 /* remove from bridge */
500 if (relation->channel_state != CHANNEL_STATE_HOLD)
502 relation->channel_state = CHANNEL_STATE_HOLD;
503 j_updatebridge = 1; /* update bridge flag */
504 // note: if join is not released, bridge must be updated
507 /* detach given interface */
508 reltemp = j_relation;
509 relationpointer = &j_relation;
512 /* endpoint of function call */
513 if (relation == reltemp)
515 relationpointer = &reltemp->next;
516 reltemp = reltemp->next;
519 FATAL("relation not in list of our relations. this must not happen.\n");
520 //printf("releasing relation %d\n", reltemp->epoint_id);
521 *relationpointer = reltemp->next;
522 FREE(reltemp, sizeof(struct join_relation));
524 relation = reltemp = NULL; // just in case of reuse fault;
526 /* if no more relation */
529 PDEBUG(DEBUG_JOIN, "join is completely removed.\n");
530 /* there is no more endpoint related to the join */
533 // end of join object!
534 PDEBUG(DEBUG_JOIN, "join completely removed!\n");
536 /* if join is a party line */
539 PDEBUG(DEBUG_JOIN, "join is a conference room, so we keep it alive until the last party left.\n");
541 /* if only one relation left */
542 if (!j_relation->next)
544 PDEBUG(DEBUG_JOIN, "join has one relation left, so we send it a release with the given cause %d.\n", cause);
545 message = message_create(j_serial, j_relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE);
546 message->param.disconnectinfo.cause = cause;
547 message->param.disconnectinfo.location = location;
548 message_put(message);
551 // end of join object!
552 PDEBUG(DEBUG_JOIN, "join completely removed!\n");
558 if (options.deb & DEBUG_JOIN && join->j_type==JOIN_TYPE_PBX)
559 joinpbx_debug((class JoinPBX *)join, "join_release{all joins left}");
562 PDEBUG(DEBUG_JOIN, "join_release(): ended.\n");
566 /* count number of relations in a join
568 int joinpbx_countrelations(unsigned long join_id)
570 struct join_relation *relation;
573 class JoinPBX *joinpbx;
575 join = find_join_id(join_id);
580 if (join->j_type != JOIN_TYPE_REMOTE)
583 if (join->j_type != JOIN_TYPE_PBX)
585 joinpbx = (class JoinPBX *)join;
588 relation = joinpbx->j_relation;
592 relation = relation->next;
598 void JoinPBX::remove_relation(struct join_relation *relation)
600 struct join_relation *temp, **tempp;
609 if (temp == relation)
616 PERROR("relation not in join.\n");
620 PDEBUG(DEBUG_JOIN, "removing relation.\n");
621 *tempp = relation->next;
622 FREE(temp, sizeof(struct join_relation));
627 struct join_relation *JoinPBX::add_relation(void)
629 struct join_relation *relation;
633 PERROR("there is no first relation to this join\n");
636 relation = j_relation;
637 while(relation->next)
638 relation = relation->next;
640 relation->next = (struct join_relation *)MALLOC(sizeof(struct join_relation));
642 /* the record pointer is set at the first time the data is received for the relation */
644 // if (options.deb & DEBUG_JOIN)
645 // joinpbx_debug(join, "add_relation");
646 return(relation->next);
649 /* epoint sends a message to a join
652 void JoinPBX::message_epoint(unsigned long epoint_id, int message_type, union parameter *param)
655 struct join_relation *relation, *reltemp;
658 struct message *message;
659 // int size, writesize, oldpointer;
660 char *number, *numbers;
664 PERROR("software error, epoint == NULL\n");
668 // if (options.deb & DEBUG_JOIN)
670 // PDEBUG(DEBUG_JOIN, "message %d received from ep%d.\n", message, epoint->ep_serial);
671 // joinpbx_debug(join,"Join::message_epoint");
673 if (options.deb & DEBUG_JOIN)
675 if (message_type != MESSAGE_DATA)
680 if (cl->j_type == JOIN_TYPE_PBX)
681 joinpbx_debug((class JoinPBX *)cl, "Join::message_epoint{all joins before processing}");
688 relation = j_relation;
691 if (relation->epoint_id == epoint_id)
693 relation = relation->next;
697 PDEBUG(DEBUG_JOIN, "no relation back to the endpoint found, ignoring (join=%d, endpoint=%d)\n", j_serial, epoint_id);
701 /* process party line */
702 if (message_type == MESSAGE_SETUP) if (param->setup.partyline)
704 j_partyline = param->setup.partyline;
711 PDEBUG(DEBUG_JOIN, "respsone with connect in partyline mode.\n");
712 relation->type = RELATION_TYPE_CONNECT;
713 message = message_create(j_serial, epoint_id, JOIN_TO_EPOINT, MESSAGE_CONNECT);
714 SPRINT(message->param.connectinfo.id, "%d", j_partyline);
715 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
716 message_put(message);
717 j_updatebridge = 1; /* update bridge flag */
720 case MESSAGE_AUDIOPATH:
721 PDEBUG(DEBUG_JOIN, "join received channel message: %d.\n", param->audiopath);
722 if (relation->channel_state != param->audiopath)
724 relation->channel_state = param->audiopath;
725 j_updatebridge = 1; /* update bridge flag */
726 if (options.deb & DEBUG_JOIN)
727 joinpbx_debug(this, "Join::message_epoint{after setting new channel state}");
731 case MESSAGE_DISCONNECT:
732 PDEBUG(DEBUG_JOIN, "releasing after receiving disconnect, because join in partyline mode.\n");
733 message = message_create(j_serial, epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE);
734 message->param.disconnectinfo.cause = CAUSE_NORMAL;
735 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
736 message_put(message);
739 case MESSAGE_RELEASE:
740 PDEBUG(DEBUG_JOIN, "releasing from join\n");
741 release(relation, 0, 0);
745 PDEBUG(DEBUG_JOIN, "ignoring message, because join in partyline mode.\n");
751 /* process messages */
754 /* process audio path message */
755 case MESSAGE_AUDIOPATH:
756 PDEBUG(DEBUG_JOIN, "join received channel message: %d.\n", param->audiopath);
757 if (relation->channel_state != param->audiopath)
759 relation->channel_state = param->audiopath;
760 j_updatebridge = 1; /* update bridge flag */
761 if (options.deb & DEBUG_JOIN)
762 joinpbx_debug(this, "Join::message_epoint{after setting new channel state}");
768 switch(param->notifyinfo.notify)
770 case INFO_NOTIFY_USER_SUSPENDED:
771 case INFO_NOTIFY_USER_RESUMED:
772 case INFO_NOTIFY_REMOTE_HOLD:
773 case INFO_NOTIFY_REMOTE_RETRIEVAL:
774 case INFO_NOTIFY_CONFERENCE_ESTABLISHED:
775 case INFO_NOTIFY_CONFERENCE_DISCONNECTED:
776 new_state = track_notify(relation->rx_state, param->notifyinfo.notify);
777 if (new_state != relation->rx_state)
779 relation->rx_state = new_state;
781 if (options.deb & DEBUG_JOIN)
782 joinpbx_debug(this, "Join::message_epoint{after setting new rx state}");
787 /* send notification to all other endpoints */
788 reltemp = j_relation;
791 if (reltemp->epoint_id!=epoint_id && reltemp->epoint_id)
793 message = message_create(j_serial, reltemp->epoint_id, JOIN_TO_EPOINT, MESSAGE_NOTIFY);
794 memcpy(&message->param, param, sizeof(union parameter));
795 message_put(message);
797 reltemp = reltemp->next;
804 /* now send audio data to the other endpoint */
805 bridge_data(epoint_id, relation, param);
808 /* relations sends a connect */
809 case MESSAGE_CONNECT:
810 /* outgoing setup type becomes connected */
811 if (relation->type == RELATION_TYPE_SETUP)
812 relation->type = RELATION_TYPE_CONNECT;
813 /* release other relations in setup state */
815 reltemp = j_relation;
818 //printf("connect, checking relation %d\n", reltemp->epoint_id);
819 if (reltemp->type == RELATION_TYPE_SETUP)
821 //printf("relation %d is of type setup, releasing\n", reltemp->epoint_id);
822 /* send release to endpoint */
823 message = message_create(j_serial, reltemp->epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE);
824 message->param.disconnectinfo.cause = CAUSE_NONSELECTED;
825 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
826 message_put(message);
828 if (release(reltemp, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL)) // dummy cause, should not be used, since calling and connected endpoint still exist afterwards.
829 return; // must return, because join IS destroyed
832 if (reltemp->type == RELATION_TYPE_CALLING)
833 reltemp->type = RELATION_TYPE_CONNECT;
834 reltemp = reltemp->next;
836 break; // continue with our message
838 /* release is sent by endpoint */
839 case MESSAGE_RELEASE:
840 switch(relation->type)
842 case RELATION_TYPE_SETUP: /* by called */
843 /* collect cause and send collected cause */
844 collect_cause(&j_multicause, &j_multilocation, param->disconnectinfo.cause, param->disconnectinfo.location);
846 release(relation, j_multilocation, j_multicause);
848 release(relation, LOCATION_PRIVATE_LOCAL, CAUSE_UNSPECIFIED);
851 case RELATION_TYPE_CALLING: /* by calling */
852 /* remove all relations that are in called */
854 reltemp = j_relation;
857 if (reltemp->type == RELATION_TYPE_SETUP)
859 /* send release to endpoint */
860 message = message_create(j_serial, reltemp->epoint_id, JOIN_TO_EPOINT, message_type);
861 memcpy(&message->param, param, sizeof(union parameter));
862 message_put(message);
864 if (release(reltemp, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL))
865 return; // must return, because join IS destroyed
868 reltemp = reltemp->next;
870 PERROR("we are still here, this should not happen\n");
873 default: /* by connected */
874 /* send current cause */
875 release(relation, param->disconnectinfo.location, param->disconnectinfo.cause);
877 return; // must return, because join may be destroyed
880 /* count relations */
881 num=joinpbx_countrelations(j_serial);
883 /* check number of relations */
886 PDEBUG(DEBUG_JOIN, "join has more than two relations so there is no need to send a message.\n");
890 /* find interfaces not related to calling epoint */
891 relation = j_relation;
894 if (relation->epoint_id != epoint_id)
896 relation = relation->next;
903 if (param->setup.dialinginfo.itype == INFO_ITYPE_ISDN_EXTENSION)
905 numbers = param->setup.dialinginfo.id;
906 while((number = strsep(&numbers, ",")))
908 if (out_setup(epoint_id, message_type, param, number))
909 return; // join destroyed
913 if (out_setup(epoint_id, message_type, param, NULL))
914 return; // join destroyed
918 PDEBUG(DEBUG_JOIN, "no need to send a message because there is no other endpoint than the calling one.\n");
922 PDEBUG(DEBUG_JOIN, "sending message ep%ld -> ep%ld.\n", epoint_id, relation->epoint_id);
923 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, message_type);
924 memcpy(&message->param, param, sizeof(union parameter));
925 message_put(message);
926 PDEBUG(DEBUG_JOIN, "message sent.\n");
931 /* join process is called from the main loop
932 * it processes the current calling state.
933 * returns 0 if join nothing was done
935 int JoinPBX::handler(void)
937 // struct join_relation *relation;
938 // char dialing[32][32];
944 /* the bridge must be updated */
956 int track_notify(int oldstate, int notify)
958 int newstate = oldstate;
962 case INFO_NOTIFY_USER_RESUMED:
963 case INFO_NOTIFY_REMOTE_RETRIEVAL:
964 case INFO_NOTIFY_CONFERENCE_DISCONNECTED:
965 case INFO_NOTIFY_RESERVED_CT_1:
966 case INFO_NOTIFY_RESERVED_CT_2:
967 case INFO_NOTIFY_CALL_IS_DIVERTING:
968 newstate = NOTIFY_STATE_ACTIVE;
971 case INFO_NOTIFY_USER_SUSPENDED:
972 newstate = NOTIFY_STATE_SUSPEND;
975 case INFO_NOTIFY_REMOTE_HOLD:
976 newstate = NOTIFY_STATE_HOLD;
979 case INFO_NOTIFY_CONFERENCE_ESTABLISHED:
980 newstate = NOTIFY_STATE_CONFERENCE;
989 * setup to exactly one endpoint
990 * if it fails, the calling endpoint is released.
991 * if other outgoing endpoints already exists, they are release as well.
992 * note: if this functions fails, it will destroy its own join object!
994 int JoinPBX::out_setup(unsigned long epoint_id, int message_type, union parameter *param, char *newnumber)
996 struct join_relation *relation;
997 struct message *message;
998 class Endpoint *epoint;
1000 PDEBUG(DEBUG_JOIN, "no endpoint found, so we will create an endpoint and send the setup message we have.\n");
1001 /* create a new relation */
1002 if (!(relation=add_relation()))
1003 FATAL("No memory for relation.\n");
1004 relation->type = RELATION_TYPE_SETUP;
1005 relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new join */
1006 relation->tx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
1007 relation->rx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
1008 /* create a new endpoint */
1009 epoint = new Endpoint(0, j_serial);
1011 FATAL("No memory for Endpoint instance\n");
1012 if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint)))
1013 FATAL("No memory for Endpoint Application instance\n");
1014 relation->epoint_id = epoint->ep_serial;
1015 /* send setup message to new endpoint */
1016 //printf("JOLLY DEBUG: %d\n",join_countrelations(j_serial));
1017 //i if (options.deb & DEBUG_JOIN)
1018 // joinpbx_debug(join, "Join::message_epoint");
1019 message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, message_type);
1020 memcpy(&message->param, param, sizeof(union parameter));
1022 SCPY(message->param.setup.dialinginfo.id, newnumber);
1023 PDEBUG(DEBUG_JOIN, "setup message sent to ep %d with number='%s'.\n", relation->epoint_id, message->param.setup.dialinginfo.id);
1024 message_put(message);