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; // relations that are no mISDN
315 relation = c_relation;
318 /* count all relations */
321 /* check for relation's objects */
322 epoint = find_epoint_id(relation->epoint_id);
325 PERROR("software error: relation without existing endpoints.\n");
326 relation = relation->next;
329 portlist = epoint->ep_portlist;
332 PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation without port object.\n");
333 //#warning testing: keep on hold until single audio stream available
334 relation->channel_state = CHANNEL_STATE_HOLD;
335 relation = relation->next;
340 PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation with ep%d due to port_list.\n", epoint->ep_serial);
341 //#warning testing: keep on hold until single audio stream available
342 relation->channel_state = CHANNEL_STATE_HOLD;
343 relation = relation->next;
346 port = find_port_id(portlist->port_id);
349 PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation without existing port object.\n");
350 relation = relation->next;
353 if ((port->p_type&PORT_CLASS_MASK)!=PORT_CLASS_mISDN)
355 PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation ep%d because it's port is not mISDN.\n", epoint->ep_serial);
358 PDEBUG((DEBUG_CALL|DEBUG_PORT), "not all endpoints are mISDN.\n");
361 relation = relation->next;
364 relation = relation->next;
367 /* we notify all relations about rxdata. */
368 relation = c_relation;
371 /* count connected relations */
372 if ((relation->channel_state == CHANNEL_STATE_CONNECT)
373 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
374 && (relation->rx_state != NOTIFY_STATE_HOLD))
377 /* remove unconnected parties from conference, also remove remotely disconnected parties so conference will not be disturbed. */
378 if (relation->channel_state == CHANNEL_STATE_CONNECT
379 && relation->rx_state != NOTIFY_STATE_HOLD
380 && relation->rx_state != NOTIFY_STATE_SUSPEND
381 && relations>1 // no conf with on party
382 && allmISDN) // no conf if any member is not mISDN
384 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
385 message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
386 message->param.mISDNsignal.conf = c_serial<<16 | c_pid;
387 PDEBUG(DEBUG_CALL, "%s +on+ id: 0x%08x\n", port->p_name, message->param.mISDNsignal.conf);
388 message_put(message);
391 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
392 message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
393 message->param.mISDNsignal.conf = 0;
394 PDEBUG(DEBUG_CALL, "%s +off+ id: 0x%08x\n", port->p_name, message->param.mISDNsignal.conf);
395 message_put(message);
399 * request data from endpoint/port if:
401 * - any without mISDN
402 * in this case we bridge
404 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
405 message->param.mISDNsignal.message = mISDNSIGNAL_CALLDATA;
406 message->param.mISDNsignal.calldata = (relnum==2 && !allmISDN);
407 PDEBUG(DEBUG_CALL, "call %d sets 'calldata' on port %s to %d\n", c_serial, port->p_name, calldata);
408 message_put(message);
410 relation = relation->next;
413 /* two people just exchange their states */
414 if (relations==2 && !c_partyline)
416 relation = c_relation;
417 relation->tx_state = notify_state_change(c_serial, relation->epoint_id, relation->tx_state, relation->next->rx_state);
418 relation->next->tx_state = notify_state_change(c_serial, relation->next->epoint_id, relation->next->tx_state, relation->rx_state);
420 /* one member in a call, so we put her on hold */
421 if (relations==1 || numconnect==1)
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 * bridging is only possible with two connected endpoints
450 void CallPBX::bridge_data(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param)
452 struct call_relation *relation_to;
453 struct message *message;
455 /* if we are alone */
456 if (!c_relation->next)
459 /* if we are more than two */
460 if (c_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 = c_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 destomatopm 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 //PDEBUG(DEBUG_CALL, "mixing from %d to %d\n", epoint_from, relation_to->epoint_id);
483 message = message_create(c_serial, relation_to->epoint_id, CALL_TO_EPOINT, MESSAGE_DATA);
484 memcpy(&message->param, param, sizeof(union parameter));
485 message_put(message);
489 /* release call from endpoint
490 * if the call has two relations, all relations are freed and the call will be
493 void CallPBX::release(unsigned long epoint_id, int hold, int location, int cause)
495 struct call_relation *relation, **relationpointer;
496 struct message *message;
502 PERROR("software error, epoint is NULL.\n");
506 if (options.deb & DEBUG_CALL)
507 callpbx_debug(this, "call_release{before}");
510 relation = c_relation;
513 if (relation->epoint_id == epoint_id)
515 relation = relation->next;
519 PERROR("software error, epoint has a call with no relation to the epoint.\n");
523 /* remove from bridge */
524 if (relation->channel_state != CHANNEL_STATE_HOLD)
526 relation->channel_state = CHANNEL_STATE_HOLD;
527 c_updatebridge = 1; /* update bridge flag */
530 /* detach given interface */
531 relation = c_relation;
532 relationpointer = &c_relation;
535 /* endpoint of function call */
536 if (relation->epoint_id == epoint_id)
538 *relationpointer = relation->next;
539 memset(relation, 0, sizeof(struct call_relation));
542 relation = *relationpointer;
545 relationpointer = &relation->next;
546 relation = relation->next;
549 /* if no more relation */
552 PDEBUG(DEBUG_CALL, "call is completely removed.\n");
553 /* there is no more endpoint related to the call */
555 // end of call object!
556 PDEBUG(DEBUG_CALL, "call completely removed!\n");
558 /* if call is a party line */
561 PDEBUG(DEBUG_CALL, "call is a conference room, so we keep it alive until the last party left.\n");
563 /* if only one relation left */
564 if (!c_relation->next)
566 PDEBUG(DEBUG_CALL, "call has one relation left, so we send it a release with the given cause %d.\n", cause);
567 message = message_create(c_serial, c_relation->epoint_id, CALL_TO_EPOINT, MESSAGE_RELEASE);
568 message->param.disconnectinfo.cause = cause;
569 message->param.disconnectinfo.location = location;
570 message_put(message);
572 // end of call object!
573 PDEBUG(DEBUG_CALL, "call completely removed!\n");
579 if (options.deb & DEBUG_CALL && call->c_type==CALL_TYPE_PBX)
580 callpbx_debug((class CallPBX *)call, "call_release{all calls left}");
583 PDEBUG(DEBUG_CALL, "call_release(): ended.\n");
586 /* count number of relations in a call
588 int callpbx_countrelations(unsigned long call_id)
590 struct call_relation *relation;
593 class CallPBX *callpbx;
595 call = find_call_id(call_id);
600 if (call->c_type != CALL_TYPE_PBX)
602 callpbx = (class CallPBX *)call;
605 relation = callpbx->c_relation;
609 relation = relation->next;
615 void CallPBX::remove_relation(struct call_relation *relation)
617 struct call_relation *temp, **tempp;
626 if (temp == relation)
633 PERROR("relation not in call.\n");
637 PDEBUG(DEBUG_CALL, "removing relation.\n");
638 *tempp = relation->next;
639 memset(temp, 0, sizeof(struct call_relation));
645 struct call_relation *CallPBX::add_relation(void)
647 struct call_relation *relation;
651 PERROR("there is no first relation to this call\n");
654 relation = c_relation;
655 while(relation->next)
656 relation = relation->next;
658 relation->next = (struct call_relation *)calloc(1, sizeof(struct call_relation));
661 PERROR("no memory\n");
665 memset(relation->next, 0, sizeof(struct call_relation));
666 /* the record pointer is set at the first time the data is received for the relation */
668 // if (options.deb & DEBUG_CALL)
669 // callpbx_debug(call, "add_relation");
670 return(relation->next);
673 /* epoint sends a message to a call
676 void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union parameter *param)
679 struct call_relation *relation, *rel;
682 struct message *message;
683 // int size, writesize, oldpointer;
684 class Endpoint *epoint;
689 PERROR("software error, epoint == NULL\n");
693 // if (options.deb & DEBUG_CALL)
695 // PDEBUG(DEBUG_CALL, "message %d received from ep%d.\n", message, epoint->ep_serial);
696 // callpbx_debug(call,"Call::message_epoint");
698 if (options.deb & DEBUG_CALL)
700 if (message_type != MESSAGE_DATA)
705 if (cl->c_type == CALL_TYPE_PBX)
706 callpbx_debug((class CallPBX *)cl, "Call::message_epoint{all calls before processing}");
713 relation = c_relation;
716 if (relation->epoint_id == epoint_id)
718 relation = relation->next;
722 // PERROR("no relation back to the endpoint found, ignoring (call=%d, endpoint=%d\n", c_serial, epoint_id);
728 /* process channel message */
729 case MESSAGE_CHANNEL:
730 PDEBUG(DEBUG_CALL, "call received channel message: %d.\n", param->channel);
731 if (relation->channel_state != param->channel)
733 relation->channel_state = param->channel;
734 c_updatebridge = 1; /* update bridge flag */
735 if (options.deb & DEBUG_CALL)
736 callpbx_debug(this, "Call::message_epoint{after setting new channel state}");
742 switch(param->notifyinfo.notify)
744 case INFO_NOTIFY_USER_SUSPENDED:
745 case INFO_NOTIFY_USER_RESUMED:
746 case INFO_NOTIFY_REMOTE_HOLD:
747 case INFO_NOTIFY_REMOTE_RETRIEVAL:
748 case INFO_NOTIFY_CONFERENCE_ESTABLISHED:
749 case INFO_NOTIFY_CONFERENCE_DISCONNECTED:
750 new_state = track_notify(relation->rx_state, param->notifyinfo.notify);
751 if (new_state != relation->rx_state)
753 relation->rx_state = new_state;
755 if (options.deb & DEBUG_CALL)
756 callpbx_debug(this, "Call::message_epoint{after setting new rx state}");
761 /* send notification to all other endpoints */
765 if (rel->epoint_id!=epoint_id && rel->epoint_id)
767 message = message_create(c_serial, rel->epoint_id, CALL_TO_EPOINT, MESSAGE_NOTIFY);
768 memcpy(&message->param, param, sizeof(union parameter));
769 message_put(message);
778 /* now send audio data to the other endpoint */
779 bridge_data(epoint_id, relation, param);
783 /* process party line */
784 if (message_type == MESSAGE_SETUP) if (param->setup.partyline)
786 PDEBUG(DEBUG_CALL, "respsone with connect in partyline mode.\n");
787 c_partyline = param->setup.partyline;
788 message = message_create(c_serial, epoint_id, CALL_TO_EPOINT, MESSAGE_CONNECT);
789 message->param.setup.partyline = c_partyline;
790 message_put(message);
791 c_updatebridge = 1; /* update bridge flag */
795 if (message_type == MESSAGE_DISCONNECT)
797 PDEBUG(DEBUG_CALL, "releasing after receiving disconnect, because call in partyline mode.\n");
798 // remove_relation(relation);
799 message = message_create(c_serial, epoint_id, CALL_TO_EPOINT, MESSAGE_RELEASE);
800 message->param.disconnectinfo.cause = CAUSE_NORMAL;
801 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
802 message_put(message);
803 // c_updatebridge = 1; /* update bridge flag */
809 PDEBUG(DEBUG_CALL, "ignoring message, because call in partyline mode.\n");
813 /* count relations */
814 num=callpbx_countrelations(c_serial);
816 /* check number of relations */
819 PDEBUG(DEBUG_CALL, "call has more than two relations so there is no need to send a message.\n");
823 /* find interfaces not related to calling epoint */
824 relation = c_relation;
827 if (relation->epoint_id != epoint_id)
829 relation = relation->next;
836 if (param->dialinginfo.itype == INFO_ITYPE_ISDN_EXTENSION)
838 while(number = strsep(¶m->dialinginfo.number, ','))
840 if (out_setup(epoint_id, message_type, param, number))
841 return; // call destroyed
845 if (out_setup(epoint_id, message_type, param, NULL))
846 return; // call destroyed
850 PDEBUG(DEBUG_CALL, "no need to send a message because there is no other endpoint than the calling one.\n");
854 PDEBUG(DEBUG_CALL, "sending message ep%ld -> ep%ld.\n", epoint_id, relation->epoint_id);
855 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, message_type);
856 memcpy(&message->param, param, sizeof(union parameter));
857 message_put(message);
858 PDEBUG(DEBUG_CALL, "message sent.\n");
863 /* call process is called from the main loop
864 * it processes the current calling state.
865 * returns 0 if call nothing was done
867 int CallPBX::handler(void)
869 // struct call_relation *relation;
870 // char dialing[32][32];
876 /* the bridge must be updated */
888 int track_notify(int oldstate, int notify)
890 int newstate = oldstate;
894 case INFO_NOTIFY_USER_RESUMED:
895 case INFO_NOTIFY_REMOTE_RETRIEVAL:
896 case INFO_NOTIFY_CONFERENCE_DISCONNECTED:
897 case INFO_NOTIFY_RESERVED_CT_1:
898 case INFO_NOTIFY_RESERVED_CT_2:
899 case INFO_NOTIFY_CALL_IS_DIVERTING:
900 newstate = NOTIFY_STATE_ACTIVE;
903 case INFO_NOTIFY_USER_SUSPENDED:
904 newstate = NOTIFY_STATE_SUSPEND;
907 case INFO_NOTIFY_REMOTE_HOLD:
908 newstate = NOTIFY_STATE_HOLD;
911 case INFO_NOTIFY_CONFERENCE_ESTABLISHED:
912 newstate = NOTIFY_STATE_CONFERENCE;
921 * setup to exactly one endpoint
922 * if it fails, the calling endpoint is released.
923 * if other outgoing endpoints already exists, they are release as well.
924 * note: if this functions fails, it will destroy its own call object!
926 int CallPBX::out_setup(unsigned long epoint_id, int message_type, union parameter *param, char *newnumber)
928 struct call_relation *relation;
929 struct message *message;
930 class Endpoint *epoint;
932 PDEBUG(DEBUG_CALL, "no endpoint found, so we will create an endpoint and send the setup message we have.\n");
933 /* create a new relation */
934 if (!(relation=add_relation()))
936 /* release due to error */
938 relation = c_relation;
941 message = message_create(c_serial, releation->epoint_id, CALL_TO_EPOINT, MESSAGE_RELEASE);
942 message->param.disconnectinfo.cause = (relation->epoint_id==epoint_id)CAUSE_RESSOURCEUNAVAIL?:CAUSE_NORMAL;
943 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
944 message_put(message);
945 relation = relation->next;
950 relation->type = RELATION_TYPE_SETUP;
951 relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new call */
952 relation->tx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
953 relation->rx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
954 /* create a new endpoint */
955 epoint = new Endpoint(0, c_serial);
958 remove_relation(relation);
959 goto ressource_error;
961 if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint)))
963 PERROR("ERROR:No endpoint's app.\n");
965 remove_relation(relation);
966 goto ressource_error;
968 relation->epoint_id = epoint->ep_serial;
969 /* send setup message to new endpoint */
970 //printf("JOLLY DEBUG: %d\n",call_countrelations(c_serial));
971 //i if (options.deb & DEBUG_CALL)
972 // callpbx_debug(call, "Call::message_epoint");
973 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, message_type);
974 memcpy(&message->param, param, sizeof(union parameter));
976 SCPY(message->param.setup.dialinginfo.number, newnumber);
977 PDEBUG(DEBUG_CALL, "setup message sent to ep %d with number='%s'.\n", relation->epoint_id, message->param.setup.dialinginfo.number);
978 message_put(message);
982 todo: beim release von einem relation_type_setup muss der cause gesammelt werden, bis keine weitere setup-relation mehr existiert
983 beim letzten den collected cause senden
984 bridge kann ruhig loslegen, das aber dokumentieren
985 bridge überdenken: wer sendet, welche töne verfügbar sind, u.s.w