1 /*****************************************************************************\
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 call_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 (call_id && notify_off)
107 message = message_create(call_id, epoint_id, CALL_TO_EPOINT, MESSAGE_NOTIFY);
108 message->param.notifyinfo.notify = notify_off;
109 message_put(message);
112 if (call_id && notify_on)
114 message = message_create(call_id, epoint_id, CALL_TO_EPOINT, MESSAGE_NOTIFY);
115 message->param.notifyinfo.notify = notify_on;
116 message_put(message);
123 /* debug function for call */
124 void callpbx_debug(class CallPBX *callpbx, char *function)
126 struct call_relation *relation;
127 struct port_list *portlist;
128 class Endpoint *epoint;
132 if (!(options.deb & DEBUG_CALL))
135 PDEBUG(DEBUG_CALL, "CALL(%d) start (called from %s)\n", callpbx->c_serial, function);
137 relation = callpbx->c_relation;
140 PDEBUG(DEBUG_CALL, "call has no relations\n");
143 epoint = find_epoint_id(relation->epoint_id);
146 PDEBUG(DEBUG_CALL, "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_call_id==callpbx->c_serial)?"yes":"no", (epoint->get_hold_id()==callpbx->c_serial)?"yes":"no");
164 UPRINT(strchr(buffer,0), " endpoint=%d on=%s", epoint->ep_serial, (epoint->ep_call_id==callpbx->c_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_CALL, "%s\n", buffer);
229 relation = relation->next;
232 PDEBUG(DEBUG_CALL, "end\n");
237 * constructor for a new call
238 * the call will have a relation to the calling endpoint
240 CallPBX::CallPBX(class Endpoint *epoint) : Call(epoint)
242 struct call_relation *relation;
243 // char filename[256];
247 PERROR("software error, epoint is NULL.\n");
251 PDEBUG(DEBUG_CALL, "creating new call and connecting it to the endpoint.\n");
253 c_type = CALL_TYPE_PBX;
255 c_caller_id[0] = '\0';
262 /* initialize a relation only to the calling interface */
263 relation = c_relation = (struct call_relation *)calloc(1, sizeof(struct call_relation));
266 PERROR("no memory, exitting..\n");
270 memset(relation, 0, sizeof(struct call_relation));
271 relation->type = RELATION_TYPE_CALLING;
272 relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new call */
273 relation->tx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
274 relation->rx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
275 relation->epoint_id = epoint->ep_serial;
278 if (options.deb & DEBUG_CALL)
279 callpbx_debug(this, "CallPBX::Constructor(new call)");
288 struct call_relation *relation, *rtemp;
290 relation = c_relation;
293 rtemp = relation->next;
294 memset(relation, 0, sizeof(struct call_relation));
302 /* bridge sets the audio flow of all bchannels assiociated to 'this' call
303 * also it changes and notifies active/hold/conference states
305 void CallPBX::bridge(void)
307 struct call_relation *relation;
308 struct message *message;
309 int numconnect = 0, relations = 0;
310 class Endpoint *epoint;
311 struct port_list *portlist;
313 int allmISDN = 0; // set until a non-mISDN relation is found
316 relation = c_relation;
319 /* count all relations */
322 /* check for relation's objects */
323 epoint = find_epoint_id(relation->epoint_id);
326 PERROR("software error: relation without existing endpoints.\n");
327 relation = relation->next;
330 portlist = epoint->ep_portlist;
333 PDEBUG(DEBUG_CALL, "CALL%d ignoring relation without port object.\n", c_serial);
334 //#warning testing: keep on hold until single audio stream available
335 relation->channel_state = CHANNEL_STATE_HOLD;
336 relation = relation->next;
341 PDEBUG(DEBUG_CALL, "CALL%d ignoring relation with ep%d due to port_list.\n", c_serial, epoint->ep_serial);
342 //#warning testing: keep on hold until single audio stream available
343 relation->channel_state = CHANNEL_STATE_HOLD;
344 relation = relation->next;
347 port = find_port_id(portlist->port_id);
350 PDEBUG(DEBUG_CALL, "CALL%d ignoring relation without existing port object.\n", c_serial);
351 relation = relation->next;
354 if ((port->p_type&PORT_CLASS_MASK)!=PORT_CLASS_mISDN)
356 PDEBUG(DEBUG_CALL, "CALL%d ignoring relation ep%d because it's port is not mISDN.\n", c_serial, epoint->ep_serial);
359 PDEBUG(DEBUG_CALL, "CALL%d not all endpoints are mISDN.\n", c_serial);
362 relation = relation->next;
366 relation = relation->next;
369 PDEBUG(DEBUG_CALL, "CALL%d members=%d %s\n", c_serial, relations, (allmISDN)?"(all are mISDN-members)":"(not all are mISDN-members)");
370 /* we notify all relations about rxdata. */
371 relation = c_relation;
374 /* count connected relations */
375 if ((relation->channel_state == CHANNEL_STATE_CONNECT)
376 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
377 && (relation->rx_state != NOTIFY_STATE_HOLD))
380 /* remove unconnected parties from conference, also remove remotely disconnected parties so conference will not be disturbed. */
381 if (relation->channel_state == CHANNEL_STATE_CONNECT
382 && relation->rx_state != NOTIFY_STATE_HOLD
383 && relation->rx_state != NOTIFY_STATE_SUSPEND
384 && relations>1 // no conf with one member
385 && allmISDN) // no conf if any member is not mISDN
387 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
388 message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
389 message->param.mISDNsignal.conf = c_serial<<16 | c_pid;
390 PDEBUG(DEBUG_CALL, "CALL%d EP%d +on+ id: 0x%08x\n", c_serial, relation->epoint_id, message->param.mISDNsignal.conf);
391 message_put(message);
394 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
395 message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
396 message->param.mISDNsignal.conf = 0;
397 PDEBUG(DEBUG_CALL, "CALL%d EP%d +off+ id: 0x%08x\n", c_serial, relation->epoint_id, message->param.mISDNsignal.conf);
398 message_put(message);
402 * request data from endpoint/port if:
404 * - any without mISDN
405 * in this case we bridge
407 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
408 message->param.mISDNsignal.message = mISDNSIGNAL_CALLDATA;
409 message->param.mISDNsignal.calldata = (relations==2 && !allmISDN);
410 PDEBUG(DEBUG_CALL, "CALL%d EP%d set calldata=%d\n", c_serial, relation->epoint_id, message->param.mISDNsignal.calldata);
411 message_put(message);
413 relation = relation->next;
416 /* two people just exchange their states */
417 if (relations==2 && !c_partyline)
419 PDEBUG(DEBUG_CALL, "CALL%d 2 relations / no partyline\n", c_serial);
420 relation = c_relation;
421 relation->tx_state = notify_state_change(c_serial, relation->epoint_id, relation->tx_state, relation->next->rx_state);
422 relation->next->tx_state = notify_state_change(c_serial, relation->next->epoint_id, relation->next->tx_state, relation->rx_state);
424 /* one member in a call, so we put her on hold */
425 if (relations==1 || numconnect==1)
427 PDEBUG(DEBUG_CALL, "CALL%d 1 member or only 1 connected, put on hold\n");
428 relation = c_relation;
431 if ((relation->channel_state == CHANNEL_STATE_CONNECT)
432 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
433 && (relation->rx_state != NOTIFY_STATE_HOLD))
434 relation->tx_state = notify_state_change(c_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_HOLD);
435 relation = relation->next;
438 /* if conference/partyline or (more than two members and more than one is connected), so we set conference state */
440 PDEBUG(DEBUG_CALL, "CALL%d %d members, %d connected, signal conference\n", relations, numconnect);
441 relation = c_relation;
444 if ((relation->channel_state == CHANNEL_STATE_CONNECT)
445 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
446 && (relation->rx_state != NOTIFY_STATE_HOLD))
447 relation->tx_state = notify_state_change(c_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_CONFERENCE);
448 relation = relation->next;
454 * bridging is only possible with two connected endpoints
456 void CallPBX::bridge_data(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param)
458 struct call_relation *relation_to;
459 struct message *message;
461 /* if we are alone */
462 if (!c_relation->next)
465 /* if we are more than two */
466 if (c_relation->next->next)
469 /* skip if source endpoint has NOT audio mode CONNECT */
470 if (relation_from->channel_state != CHANNEL_STATE_CONNECT)
473 /* get destination relation */
474 relation_to = c_relation;
475 if (relation_to == relation_from)
477 /* oops, we are the first, so destination is: */
478 relation_to = relation_to->next;
481 /* skip if destination endpoint has NOT audio mode CONNECT */
482 if (relation_to->channel_state != CHANNEL_STATE_CONNECT)
485 /* now we may send our data to the endpoint where it
486 * will be delivered to the port
488 //PDEBUG(DEBUG_CALL, "mixing from %d to %d\n", epoint_from, relation_to->epoint_id);
489 printf("from %d, to %d\n", relation_from->epoint_id, relation_to->epoint_id);
490 message = message_create(c_serial, relation_to->epoint_id, CALL_TO_EPOINT, MESSAGE_DATA);
491 memcpy(&message->param, param, sizeof(union parameter));
492 message_put(message);
496 /* release call from endpoint
497 * if the call has two relations, all relations are freed and the call will be
500 void CallPBX::release(unsigned long epoint_id, int hold, int location, int cause)
502 struct call_relation *relation, **relationpointer;
503 struct message *message;
509 PERROR("software error, epoint is NULL.\n");
513 if (options.deb & DEBUG_CALL)
514 callpbx_debug(this, "call_release{before}");
517 relation = c_relation;
520 if (relation->epoint_id == epoint_id)
522 relation = relation->next;
526 PERROR("software error, epoint has a call with no relation to the epoint.\n");
530 /* remove from bridge */
531 if (relation->channel_state != CHANNEL_STATE_HOLD)
533 relation->channel_state = CHANNEL_STATE_HOLD;
534 c_updatebridge = 1; /* update bridge flag */
537 /* detach given interface */
538 relation = c_relation;
539 relationpointer = &c_relation;
542 /* endpoint of function call */
543 if (relation->epoint_id == epoint_id)
545 *relationpointer = relation->next;
546 memset(relation, 0, sizeof(struct call_relation));
549 relation = *relationpointer;
552 relationpointer = &relation->next;
553 relation = relation->next;
556 /* if no more relation */
559 PDEBUG(DEBUG_CALL, "call is completely removed.\n");
560 /* there is no more endpoint related to the call */
562 // end of call object!
563 PDEBUG(DEBUG_CALL, "call completely removed!\n");
565 /* if call is a party line */
568 PDEBUG(DEBUG_CALL, "call is a conference room, so we keep it alive until the last party left.\n");
570 /* if only one relation left */
571 if (!c_relation->next)
573 PDEBUG(DEBUG_CALL, "call has one relation left, so we send it a release with the given cause %d.\n", cause);
574 message = message_create(c_serial, c_relation->epoint_id, CALL_TO_EPOINT, MESSAGE_RELEASE);
575 message->param.disconnectinfo.cause = cause;
576 message->param.disconnectinfo.location = location;
577 message_put(message);
579 // end of call object!
580 PDEBUG(DEBUG_CALL, "call completely removed!\n");
586 if (options.deb & DEBUG_CALL && call->c_type==CALL_TYPE_PBX)
587 callpbx_debug((class CallPBX *)call, "call_release{all calls left}");
590 PDEBUG(DEBUG_CALL, "call_release(): ended.\n");
593 /* count number of relations in a call
595 int callpbx_countrelations(unsigned long call_id)
597 struct call_relation *relation;
600 class CallPBX *callpbx;
602 call = find_call_id(call_id);
607 if (call->c_type != CALL_TYPE_ASTERISK)
610 if (call->c_type != CALL_TYPE_PBX)
612 callpbx = (class CallPBX *)call;
615 relation = callpbx->c_relation;
619 relation = relation->next;
625 void CallPBX::remove_relation(struct call_relation *relation)
627 struct call_relation *temp, **tempp;
636 if (temp == relation)
643 PERROR("relation not in call.\n");
647 PDEBUG(DEBUG_CALL, "removing relation.\n");
648 *tempp = relation->next;
649 memset(temp, 0, sizeof(struct call_relation));
655 struct call_relation *CallPBX::add_relation(void)
657 struct call_relation *relation;
661 PERROR("there is no first relation to this call\n");
664 relation = c_relation;
665 while(relation->next)
666 relation = relation->next;
668 relation->next = (struct call_relation *)calloc(1, sizeof(struct call_relation));
671 PERROR("no memory\n");
675 memset(relation->next, 0, sizeof(struct call_relation));
676 /* the record pointer is set at the first time the data is received for the relation */
678 // if (options.deb & DEBUG_CALL)
679 // callpbx_debug(call, "add_relation");
680 return(relation->next);
683 /* epoint sends a message to a call
686 void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union parameter *param)
689 struct call_relation *relation, *rel;
692 struct message *message;
693 // int size, writesize, oldpointer;
694 char *number, *numbers;
698 PERROR("software error, epoint == NULL\n");
702 // if (options.deb & DEBUG_CALL)
704 // PDEBUG(DEBUG_CALL, "message %d received from ep%d.\n", message, epoint->ep_serial);
705 // callpbx_debug(call,"Call::message_epoint");
707 if (options.deb & DEBUG_CALL)
709 if (message_type != MESSAGE_DATA)
714 if (cl->c_type == CALL_TYPE_PBX)
715 callpbx_debug((class CallPBX *)cl, "Call::message_epoint{all calls before processing}");
722 relation = c_relation;
725 if (relation->epoint_id == epoint_id)
727 relation = relation->next;
731 // PERROR("no relation back to the endpoint found, ignoring (call=%d, endpoint=%d\n", c_serial, epoint_id);
737 /* process channel message */
738 case MESSAGE_CHANNEL:
739 PDEBUG(DEBUG_CALL, "call received channel message: %d.\n", param->channel);
740 if (relation->channel_state != param->channel)
742 relation->channel_state = param->channel;
743 c_updatebridge = 1; /* update bridge flag */
744 if (options.deb & DEBUG_CALL)
745 callpbx_debug(this, "Call::message_epoint{after setting new channel state}");
751 switch(param->notifyinfo.notify)
753 case INFO_NOTIFY_USER_SUSPENDED:
754 case INFO_NOTIFY_USER_RESUMED:
755 case INFO_NOTIFY_REMOTE_HOLD:
756 case INFO_NOTIFY_REMOTE_RETRIEVAL:
757 case INFO_NOTIFY_CONFERENCE_ESTABLISHED:
758 case INFO_NOTIFY_CONFERENCE_DISCONNECTED:
759 new_state = track_notify(relation->rx_state, param->notifyinfo.notify);
760 if (new_state != relation->rx_state)
762 relation->rx_state = new_state;
764 if (options.deb & DEBUG_CALL)
765 callpbx_debug(this, "Call::message_epoint{after setting new rx state}");
770 /* send notification to all other endpoints */
774 if (rel->epoint_id!=epoint_id && rel->epoint_id)
776 message = message_create(c_serial, rel->epoint_id, CALL_TO_EPOINT, MESSAGE_NOTIFY);
777 memcpy(&message->param, param, sizeof(union parameter));
778 message_put(message);
787 /* now send audio data to the other endpoint */
788 bridge_data(epoint_id, relation, param);
792 /* process party line */
793 if (message_type == MESSAGE_SETUP) if (param->setup.partyline)
795 PDEBUG(DEBUG_CALL, "respsone with connect in partyline mode.\n");
796 c_partyline = param->setup.partyline;
797 message = message_create(c_serial, epoint_id, CALL_TO_EPOINT, MESSAGE_CONNECT);
798 message->param.setup.partyline = c_partyline;
799 message_put(message);
800 c_updatebridge = 1; /* update bridge flag */
804 if (message_type == MESSAGE_DISCONNECT)
806 PDEBUG(DEBUG_CALL, "releasing after receiving disconnect, because call in partyline mode.\n");
807 // remove_relation(relation);
808 message = message_create(c_serial, epoint_id, CALL_TO_EPOINT, MESSAGE_RELEASE);
809 message->param.disconnectinfo.cause = CAUSE_NORMAL;
810 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
811 message_put(message);
812 // c_updatebridge = 1; /* update bridge flag */
818 PDEBUG(DEBUG_CALL, "ignoring message, because call in partyline mode.\n");
822 /* count relations */
823 num=callpbx_countrelations(c_serial);
825 /* check number of relations */
828 PDEBUG(DEBUG_CALL, "call has more than two relations so there is no need to send a message.\n");
832 /* find interfaces not related to calling epoint */
833 relation = c_relation;
836 if (relation->epoint_id != epoint_id)
838 relation = relation->next;
845 if (param->setup.dialinginfo.itype == INFO_ITYPE_ISDN_EXTENSION)
847 numbers = param->setup.dialinginfo.id;
848 while((number = strsep(&numbers, ",")))
850 if (out_setup(epoint_id, message_type, param, number))
851 return; // call destroyed
855 if (out_setup(epoint_id, message_type, param, NULL))
856 return; // call destroyed
860 PDEBUG(DEBUG_CALL, "no need to send a message because there is no other endpoint than the calling one.\n");
864 PDEBUG(DEBUG_CALL, "sending message ep%ld -> ep%ld.\n", epoint_id, relation->epoint_id);
865 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, message_type);
866 memcpy(&message->param, param, sizeof(union parameter));
867 message_put(message);
868 PDEBUG(DEBUG_CALL, "message sent.\n");
873 /* call process is called from the main loop
874 * it processes the current calling state.
875 * returns 0 if call nothing was done
877 int CallPBX::handler(void)
879 // struct call_relation *relation;
880 // char dialing[32][32];
886 /* the bridge must be updated */
898 int track_notify(int oldstate, int notify)
900 int newstate = oldstate;
904 case INFO_NOTIFY_USER_RESUMED:
905 case INFO_NOTIFY_REMOTE_RETRIEVAL:
906 case INFO_NOTIFY_CONFERENCE_DISCONNECTED:
907 case INFO_NOTIFY_RESERVED_CT_1:
908 case INFO_NOTIFY_RESERVED_CT_2:
909 case INFO_NOTIFY_CALL_IS_DIVERTING:
910 newstate = NOTIFY_STATE_ACTIVE;
913 case INFO_NOTIFY_USER_SUSPENDED:
914 newstate = NOTIFY_STATE_SUSPEND;
917 case INFO_NOTIFY_REMOTE_HOLD:
918 newstate = NOTIFY_STATE_HOLD;
921 case INFO_NOTIFY_CONFERENCE_ESTABLISHED:
922 newstate = NOTIFY_STATE_CONFERENCE;
931 * setup to exactly one endpoint
932 * if it fails, the calling endpoint is released.
933 * if other outgoing endpoints already exists, they are release as well.
934 * note: if this functions fails, it will destroy its own call object!
936 int CallPBX::out_setup(unsigned long epoint_id, int message_type, union parameter *param, char *newnumber)
938 struct call_relation *relation;
939 struct message *message;
940 class Endpoint *epoint;
942 PDEBUG(DEBUG_CALL, "no endpoint found, so we will create an endpoint and send the setup message we have.\n");
943 /* create a new relation */
944 if (!(relation=add_relation()))
946 /* release due to error */
948 relation = c_relation;
951 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_RELEASE);
952 message->param.disconnectinfo.cause = (relation->epoint_id==epoint_id)?CAUSE_RESSOURCEUNAVAIL:CAUSE_NORMAL;
953 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
954 message_put(message);
955 relation = relation->next;
960 relation->type = RELATION_TYPE_SETUP;
961 relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new call */
962 relation->tx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
963 relation->rx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
964 /* create a new endpoint */
965 epoint = new Endpoint(0, c_serial);
968 remove_relation(relation);
969 goto ressource_error;
971 if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint)))
973 PERROR("ERROR:No endpoint's app.\n");
975 remove_relation(relation);
976 goto ressource_error;
978 relation->epoint_id = epoint->ep_serial;
979 /* send setup message to new endpoint */
980 //printf("JOLLY DEBUG: %d\n",call_countrelations(c_serial));
981 //i if (options.deb & DEBUG_CALL)
982 // callpbx_debug(call, "Call::message_epoint");
983 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, message_type);
984 memcpy(&message->param, param, sizeof(union parameter));
986 SCPY(message->param.setup.dialinginfo.id, newnumber);
987 PDEBUG(DEBUG_CALL, "setup message sent to ep %d with number='%s'.\n", relation->epoint_id, message->param.setup.dialinginfo.id);
988 message_put(message);