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';
261 /* initialize a relation only to the calling interface */
262 relation = c_relation = (struct call_relation *)calloc(1, sizeof(struct call_relation));
265 PERROR("no memory, exitting..\n");
269 memset(relation, 0, sizeof(struct call_relation));
270 relation->type = RELATION_TYPE_CALLING;
271 relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new call */
272 relation->tx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
273 relation->rx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
274 relation->epoint_id = epoint->ep_serial;
277 if (options.deb & DEBUG_CALL)
278 callpbx_debug(this, "CallPBX::Constructor(new call)");
287 struct call_relation *relation, *rtemp;
289 relation = c_relation;
292 rtemp = relation->next;
293 memset(relation, 0, sizeof(struct call_relation));
301 /* mixer sets the mixer of hisax bchannels
302 * the mixer() will set the mixer for the hisax ports which is done
305 void CallPBX::mixer(void)
307 struct call_relation *relation;
308 struct message *message;
309 int numconnect, relations;
310 class Endpoint *epoint;
311 struct port_list *portlist;
315 relation = c_relation;
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_CALL|DEBUG_PORT), "ignoring relation without interfaces.\n");
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_CALL|DEBUG_PORT), "ignoring relation with ep%d due to port_list.\n", 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_CALL|DEBUG_PORT), "software error: relation without existing port.\n");
346 relation = relation->next;
351 PDEBUG(DEBUG_CALL|DEBUG_PORT, "mixer(): relation ep%d does recording, so we must get data from all members.\n", epoint->ep_serial);
354 PDEBUG(DEBUG_CALL|DEBUG_PORT, "mixer(): at least one endpoint wants data.\n");
358 if ((port->p_type&PORT_CLASS_MASK)!=PORT_CLASS_mISDN)
360 PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation ep%d because it is not mISDN.\n", epoint->ep_serial);
363 PDEBUG((DEBUG_CALL|DEBUG_PORT), "not all endpoints are mISDN.\n");
366 relation = relation->next;
369 // remove unconnected parties from conference, also remove remotely disconnected parties so conference will not be disturbed.
370 if (relation->channel_state == CHANNEL_STATE_CONNECT
371 && relation->rx_state != NOTIFY_STATE_HOLD
372 && relation->rx_state != NOTIFY_STATE_SUSPEND)
374 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
375 message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
376 message->param.mISDNsignal.conf = (c_serial<<1) + 1;
377 PDEBUG(DEBUG_CALL, "%s +on+ id: 0x%08x\n", port->p_name, message->param.mISDNsignal.conf);
378 message_put(message);
381 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
382 message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
383 message->param.mISDNsignal.conf = 0;
384 PDEBUG(DEBUG_CALL, "%s +off+ id: 0x%08x\n", port->p_name, message->param.mISDNsignal.conf);
385 message_put(message);
387 relation = relation->next;
389 /* we notify all relations about rxdata. */
390 relation = c_relation;
393 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
394 message->param.mISDNsignal.message = mISDNSIGNAL_NODATA;
395 message->param.mISDNsignal.nodata = nodata;
396 PDEBUG(DEBUG_CALL, "call %d sets alldata on port %s to %d\n", c_serial, port->p_name, nodata);
397 message_put(message);
398 relation = relation->next;
401 /* count relations and states */
402 relation = c_relation;
405 while(relation) /* count audio-connected and active relations */
408 if ((relation->channel_state == CHANNEL_STATE_CONNECT)
409 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
410 && (relation->rx_state != NOTIFY_STATE_HOLD))
412 relation = relation->next;
415 if (relations==2 && !c_partyline) /* two people just exchange their states */
417 relation = c_relation;
418 relation->tx_state = notify_state_change(c_serial, relation->epoint_id, relation->tx_state, relation->next->rx_state);
419 relation->next->tx_state = notify_state_change(c_serial, relation->next->epoint_id, relation->next->tx_state, relation->rx_state);
421 if ((relations==1 || numconnect==1) /*&& !c_partyline*/) /* one member in a call, so we put her on hold */
423 relation = c_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(c_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 relation = c_relation;
438 if ((relation->channel_state == CHANNEL_STATE_CONNECT)
439 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
440 && (relation->rx_state != NOTIFY_STATE_HOLD))
441 relation->tx_state = notify_state_change(c_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_CONFERENCE);
442 relation = relation->next;
448 /* send audio data to endpoints which do not come from an endpoint connected
449 * to an isdn port and do not go to an endpoint which is connected to an
450 * isdn port. in this case the mixing cannot be done with kernel space
452 void CallPBX::call_mixer(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param)
454 struct call_relation *relation_to;
455 struct message *message;
457 /* skip if source endpoint has NOT audio mode CONNECT */
458 if (relation_from->channel_state != CHANNEL_STATE_CONNECT)
463 /* loop all endpoints and skip the endpoint where the audio is from
464 * so we do not get a loop (echo)
466 relation_to = c_relation;
469 /* skip source endpoint */
470 if (relation_to->epoint_id == epoint_from)
472 relation_to = relation_to->next;
476 /* skip if destination endpoint has audio mode HOLD */
477 if (relation_to->channel_state != CHANNEL_STATE_CONNECT)
479 relation_to = relation_to->next;
483 /* now we may send our data to the endpoint where it
484 * will be delivered to the port
486 //PDEBUG(DEBUG_CALL, "mixing from %d to %d\n", epoint_from, relation_to->epoint_id);
487 message = message_create(c_serial, relation_to->epoint_id, CALL_TO_EPOINT, MESSAGE_DATA);
488 memcpy(&message->param, param, sizeof(union parameter));
489 message_put(message);
491 relation_to = relation_to->next;
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 mixer */
531 if (relation->channel_state != CHANNEL_STATE_HOLD)
533 relation->channel_state = CHANNEL_STATE_HOLD;
534 c_mixer = 1; /* update mixer 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_PBX)
609 callpbx = (class CallPBX *)call;
612 relation = callpbx->c_relation;
616 relation = relation->next;
622 void CallPBX::remove_relation(struct call_relation *relation)
624 struct call_relation *temp, **tempp;
633 if (temp == relation)
640 PERROR("relation not in call.\n");
644 PDEBUG(DEBUG_CALL, "removing relation.\n");
645 *tempp = relation->next;
646 memset(temp, 0, sizeof(struct call_relation));
652 struct call_relation *CallPBX::add_relation(void)
654 struct call_relation *relation;
658 PERROR("there is no first relation to this call\n");
661 relation = c_relation;
662 while(relation->next)
663 relation = relation->next;
665 relation->next = (struct call_relation *)calloc(1, sizeof(struct call_relation));
668 PERROR("no memory\n");
672 memset(relation->next, 0, sizeof(struct call_relation));
673 /* the record pointer is set at the first time the data is received for the relation */
675 // if (options.deb & DEBUG_CALL)
676 // callpbx_debug(call, "add_relation");
677 return(relation->next);
680 /* epoint sends a message to a call
683 void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union parameter *param)
686 struct call_relation *relation, *rel;
689 struct message *message;
690 // int size, writesize, oldpointer;
691 class Endpoint *epoint;
696 PERROR("software error, epoint == NULL\n");
700 // if (options.deb & DEBUG_CALL)
702 // PDEBUG(DEBUG_CALL, "message %d received from ep%d.\n", message, epoint->ep_serial);
703 // callpbx_debug(call,"Call::message_epoint");
705 if (options.deb & DEBUG_CALL)
707 if (message_type != MESSAGE_DATA)
712 if (cl->c_type == CALL_TYPE_PBX)
713 callpbx_debug((class CallPBX *)cl, "Call::message_epoint{all calls before processing}");
720 relation = c_relation;
723 if (relation->epoint_id == epoint_id)
725 relation = relation->next;
729 // PERROR("no relation back to the endpoint found, ignoring (call=%d, endpoint=%d\n", c_serial, epoint_id);
735 /* process channel message */
736 case MESSAGE_CHANNEL:
737 PDEBUG(DEBUG_CALL, "call received channel message: %d.\n", param->channel);
738 if (relation->channel_state != param->channel)
740 relation->channel_state = param->channel;
741 c_mixer = 1; /* update mixer flag */
742 if (options.deb & DEBUG_CALL)
743 callpbx_debug(this, "Call::message_epoint{after setting new channel state}");
749 switch(param->notifyinfo.notify)
751 case INFO_NOTIFY_USER_SUSPENDED:
752 case INFO_NOTIFY_USER_RESUMED:
753 case INFO_NOTIFY_REMOTE_HOLD:
754 case INFO_NOTIFY_REMOTE_RETRIEVAL:
755 case INFO_NOTIFY_CONFERENCE_ESTABLISHED:
756 case INFO_NOTIFY_CONFERENCE_DISCONNECTED:
757 new_state = track_notify(relation->rx_state, param->notifyinfo.notify);
758 if (new_state != relation->rx_state)
760 relation->rx_state = new_state;
762 if (options.deb & DEBUG_CALL)
763 callpbx_debug(this, "Call::message_epoint{after setting new rx state}");
768 /* send notification to all other endpoints */
772 if (rel->epoint_id!=epoint_id && rel->epoint_id)
774 message = message_create(c_serial, rel->epoint_id, CALL_TO_EPOINT, MESSAGE_NOTIFY);
775 memcpy(&message->param, param, sizeof(union parameter));
776 message_put(message);
785 /* now send audio data to all endpoints connected */
786 call_mixer(epoint_id, relation, param);
790 /* process party line */
791 if (message_type == MESSAGE_SETUP) if (param->setup.partyline)
793 PDEBUG(DEBUG_CALL, "respsone with connect in partyline mode.\n");
794 c_partyline = param->setup.partyline;
795 message = message_create(c_serial, epoint_id, CALL_TO_EPOINT, MESSAGE_CONNECT);
796 message->param.setup.partyline = c_partyline;
797 message_put(message);
798 c_mixer = 1; /* update mixer flag */
802 if (message_type == MESSAGE_DISCONNECT)
804 PDEBUG(DEBUG_CALL, "releasing after receiving disconnect, because call in partyline mode.\n");
805 // remove_relation(relation);
806 message = message_create(c_serial, epoint_id, CALL_TO_EPOINT, MESSAGE_RELEASE);
807 message->param.disconnectinfo.cause = CAUSE_NORMAL;
808 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
809 message_put(message);
810 // c_mixer = 1; /* update mixer flag */
816 PDEBUG(DEBUG_CALL, "ignoring message, because call in partyline mode.\n");
820 /* count relations */
821 num=callpbx_countrelations(c_serial);
823 /* check number of relations */
826 PDEBUG(DEBUG_CALL, "call has more than two relations so there is no need to send a message.\n");
830 /* find interfaces not related to calling epoint */
831 relation = c_relation;
834 if (relation->epoint_id != epoint_id)
836 relation = relation->next;
843 if (param->dialinginfo.itype == INFO_ITYPE_ISDN_EXTENSION)
845 while(number = strsep(¶m->dialinginfo.number, ','))
847 if (out_setup(epoint_id, message_type, param, number))
848 return; // call destroyed
852 if (out_setup(epoint_id, message_type, param, NULL))
853 return; // call destroyed
857 PDEBUG(DEBUG_CALL, "no need to send a message because there is no other endpoint than the calling one.\n");
861 PDEBUG(DEBUG_CALL, "sending message ep%ld -> ep%ld.\n", epoint_id, relation->epoint_id);
862 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, message_type);
863 memcpy(&message->param, param, sizeof(union parameter));
864 message_put(message);
865 PDEBUG(DEBUG_CALL, "message sent.\n");
870 /* call process is called from the main loop
871 * it processes the current calling state.
872 * returns 0 if call nothing was done
874 int CallPBX::handler(void)
876 // struct call_relation *relation;
877 // char dialing[32][32];
883 /* the mixer must be updated */
895 int track_notify(int oldstate, int notify)
897 int newstate = oldstate;
901 case INFO_NOTIFY_USER_RESUMED:
902 case INFO_NOTIFY_REMOTE_RETRIEVAL:
903 case INFO_NOTIFY_CONFERENCE_DISCONNECTED:
904 case INFO_NOTIFY_RESERVED_CT_1:
905 case INFO_NOTIFY_RESERVED_CT_2:
906 case INFO_NOTIFY_CALL_IS_DIVERTING:
907 newstate = NOTIFY_STATE_ACTIVE;
910 case INFO_NOTIFY_USER_SUSPENDED:
911 newstate = NOTIFY_STATE_SUSPEND;
914 case INFO_NOTIFY_REMOTE_HOLD:
915 newstate = NOTIFY_STATE_HOLD;
918 case INFO_NOTIFY_CONFERENCE_ESTABLISHED:
919 newstate = NOTIFY_STATE_CONFERENCE;
928 * setup to exactly one endpoint
929 * if it fails, the calling endpoint is released.
930 * if other outgoing endpoints already exists, they are release as well.
931 * note: if this functions fails, it will destroy its own call object!
933 int CallPBX::out_setup(unsigned long epoint_id, int message_type, union parameter *param, char *newnumber)
935 struct call_relation *relation;
936 struct message *message;
937 class Endpoint *epoint;
939 PDEBUG(DEBUG_CALL, "no endpoint found, so we will create an endpoint and send the setup message we have.\n");
940 /* create a new relation */
941 if (!(relation=add_relation()))
943 /* release due to error */
945 relation = c_relation;
948 message = message_create(c_serial, releation->epoint_id, CALL_TO_EPOINT, MESSAGE_RELEASE);
949 message->param.disconnectinfo.cause = (relation->epoint_id==epoint_id)CAUSE_RESSOURCEUNAVAIL?:CAUSE_NORMAL;
950 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
951 message_put(message);
952 relation = relation->next;
957 relation->type = RELATION_TYPE_SETUP;
958 relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new call */
959 relation->tx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
960 relation->rx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
961 /* create a new endpoint */
962 epoint = new Endpoint(0, c_serial);
965 remove_relation(relation);
966 goto ressource_error;
968 if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint)))
970 PERROR("ERROR:No endpoint's app.\n");
972 remove_relation(relation);
973 goto ressource_error;
975 relation->epoint_id = epoint->ep_serial;
976 /* send setup message to new endpoint */
977 //printf("JOLLY DEBUG: %d\n",call_countrelations(c_serial));
978 //i if (options.deb & DEBUG_CALL)
979 // callpbx_debug(call, "Call::message_epoint");
980 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, message_type);
981 memcpy(&message->param, param, sizeof(union parameter));
983 SCPY(message->param.setup.dialinginfo.number, newnumber);
984 PDEBUG(DEBUG_CALL, "setup message sent to ep %d with number='%s'.\n", relation->epoint_id, message->param.setup.dialinginfo.number);
985 message_put(message);
989 todo: beim release von einem relation_type_setup muss der cause gesammelt werden, bis keine weitere setup-relation mehr existiert
990 beim letzten den collected cause senden
991 mixer kann ruhig loslegen, das aber dokumentieren
992 mixer überdenken: wer sendet, welche töne verfügbar sind, u.s.w