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 = (relations==2 && !allmISDN);
407 PDEBUG(DEBUG_CALL, "call %d sets 'calldata' on port %s to %d\n", c_serial, port->p_name, message->param.mISDNsignal.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_ASTERISK)
603 if (call->c_type != CALL_TYPE_PBX)
605 callpbx = (class CallPBX *)call;
608 relation = callpbx->c_relation;
612 relation = relation->next;
618 void CallPBX::remove_relation(struct call_relation *relation)
620 struct call_relation *temp, **tempp;
629 if (temp == relation)
636 PERROR("relation not in call.\n");
640 PDEBUG(DEBUG_CALL, "removing relation.\n");
641 *tempp = relation->next;
642 memset(temp, 0, sizeof(struct call_relation));
648 struct call_relation *CallPBX::add_relation(void)
650 struct call_relation *relation;
654 PERROR("there is no first relation to this call\n");
657 relation = c_relation;
658 while(relation->next)
659 relation = relation->next;
661 relation->next = (struct call_relation *)calloc(1, sizeof(struct call_relation));
664 PERROR("no memory\n");
668 memset(relation->next, 0, sizeof(struct call_relation));
669 /* the record pointer is set at the first time the data is received for the relation */
671 // if (options.deb & DEBUG_CALL)
672 // callpbx_debug(call, "add_relation");
673 return(relation->next);
676 /* epoint sends a message to a call
679 void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union parameter *param)
682 struct call_relation *relation, *rel;
685 struct message *message;
686 // int size, writesize, oldpointer;
687 char *number, *numbers;
691 PERROR("software error, epoint == NULL\n");
695 // if (options.deb & DEBUG_CALL)
697 // PDEBUG(DEBUG_CALL, "message %d received from ep%d.\n", message, epoint->ep_serial);
698 // callpbx_debug(call,"Call::message_epoint");
700 if (options.deb & DEBUG_CALL)
702 if (message_type != MESSAGE_DATA)
707 if (cl->c_type == CALL_TYPE_PBX)
708 callpbx_debug((class CallPBX *)cl, "Call::message_epoint{all calls before processing}");
715 relation = c_relation;
718 if (relation->epoint_id == epoint_id)
720 relation = relation->next;
724 // PERROR("no relation back to the endpoint found, ignoring (call=%d, endpoint=%d\n", c_serial, epoint_id);
730 /* process channel message */
731 case MESSAGE_CHANNEL:
732 PDEBUG(DEBUG_CALL, "call received channel message: %d.\n", param->channel);
733 if (relation->channel_state != param->channel)
735 relation->channel_state = param->channel;
736 c_updatebridge = 1; /* update bridge flag */
737 if (options.deb & DEBUG_CALL)
738 callpbx_debug(this, "Call::message_epoint{after setting new channel state}");
744 switch(param->notifyinfo.notify)
746 case INFO_NOTIFY_USER_SUSPENDED:
747 case INFO_NOTIFY_USER_RESUMED:
748 case INFO_NOTIFY_REMOTE_HOLD:
749 case INFO_NOTIFY_REMOTE_RETRIEVAL:
750 case INFO_NOTIFY_CONFERENCE_ESTABLISHED:
751 case INFO_NOTIFY_CONFERENCE_DISCONNECTED:
752 new_state = track_notify(relation->rx_state, param->notifyinfo.notify);
753 if (new_state != relation->rx_state)
755 relation->rx_state = new_state;
757 if (options.deb & DEBUG_CALL)
758 callpbx_debug(this, "Call::message_epoint{after setting new rx state}");
763 /* send notification to all other endpoints */
767 if (rel->epoint_id!=epoint_id && rel->epoint_id)
769 message = message_create(c_serial, rel->epoint_id, CALL_TO_EPOINT, MESSAGE_NOTIFY);
770 memcpy(&message->param, param, sizeof(union parameter));
771 message_put(message);
780 /* now send audio data to the other endpoint */
781 bridge_data(epoint_id, relation, param);
785 /* process party line */
786 if (message_type == MESSAGE_SETUP) if (param->setup.partyline)
788 PDEBUG(DEBUG_CALL, "respsone with connect in partyline mode.\n");
789 c_partyline = param->setup.partyline;
790 message = message_create(c_serial, epoint_id, CALL_TO_EPOINT, MESSAGE_CONNECT);
791 message->param.setup.partyline = c_partyline;
792 message_put(message);
793 c_updatebridge = 1; /* update bridge flag */
797 if (message_type == MESSAGE_DISCONNECT)
799 PDEBUG(DEBUG_CALL, "releasing after receiving disconnect, because call in partyline mode.\n");
800 // remove_relation(relation);
801 message = message_create(c_serial, epoint_id, CALL_TO_EPOINT, MESSAGE_RELEASE);
802 message->param.disconnectinfo.cause = CAUSE_NORMAL;
803 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
804 message_put(message);
805 // c_updatebridge = 1; /* update bridge flag */
811 PDEBUG(DEBUG_CALL, "ignoring message, because call in partyline mode.\n");
815 /* count relations */
816 num=callpbx_countrelations(c_serial);
818 /* check number of relations */
821 PDEBUG(DEBUG_CALL, "call has more than two relations so there is no need to send a message.\n");
825 /* find interfaces not related to calling epoint */
826 relation = c_relation;
829 if (relation->epoint_id != epoint_id)
831 relation = relation->next;
838 if (param->setup.dialinginfo.itype == INFO_ITYPE_ISDN_EXTENSION)
840 numbers = param->setup.dialinginfo.id;
841 while((number = strsep(&numbers, ",")))
843 if (out_setup(epoint_id, message_type, param, number))
844 return; // call destroyed
848 if (out_setup(epoint_id, message_type, param, NULL))
849 return; // call destroyed
853 PDEBUG(DEBUG_CALL, "no need to send a message because there is no other endpoint than the calling one.\n");
857 PDEBUG(DEBUG_CALL, "sending message ep%ld -> ep%ld.\n", epoint_id, relation->epoint_id);
858 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, message_type);
859 memcpy(&message->param, param, sizeof(union parameter));
860 message_put(message);
861 PDEBUG(DEBUG_CALL, "message sent.\n");
866 /* call process is called from the main loop
867 * it processes the current calling state.
868 * returns 0 if call nothing was done
870 int CallPBX::handler(void)
872 // struct call_relation *relation;
873 // char dialing[32][32];
879 /* the bridge must be updated */
891 int track_notify(int oldstate, int notify)
893 int newstate = oldstate;
897 case INFO_NOTIFY_USER_RESUMED:
898 case INFO_NOTIFY_REMOTE_RETRIEVAL:
899 case INFO_NOTIFY_CONFERENCE_DISCONNECTED:
900 case INFO_NOTIFY_RESERVED_CT_1:
901 case INFO_NOTIFY_RESERVED_CT_2:
902 case INFO_NOTIFY_CALL_IS_DIVERTING:
903 newstate = NOTIFY_STATE_ACTIVE;
906 case INFO_NOTIFY_USER_SUSPENDED:
907 newstate = NOTIFY_STATE_SUSPEND;
910 case INFO_NOTIFY_REMOTE_HOLD:
911 newstate = NOTIFY_STATE_HOLD;
914 case INFO_NOTIFY_CONFERENCE_ESTABLISHED:
915 newstate = NOTIFY_STATE_CONFERENCE;
924 * setup to exactly one endpoint
925 * if it fails, the calling endpoint is released.
926 * if other outgoing endpoints already exists, they are release as well.
927 * note: if this functions fails, it will destroy its own call object!
929 int CallPBX::out_setup(unsigned long epoint_id, int message_type, union parameter *param, char *newnumber)
931 struct call_relation *relation;
932 struct message *message;
933 class Endpoint *epoint;
935 PDEBUG(DEBUG_CALL, "no endpoint found, so we will create an endpoint and send the setup message we have.\n");
936 /* create a new relation */
937 if (!(relation=add_relation()))
939 /* release due to error */
941 relation = c_relation;
944 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_RELEASE);
945 message->param.disconnectinfo.cause = (relation->epoint_id==epoint_id)?CAUSE_RESSOURCEUNAVAIL:CAUSE_NORMAL;
946 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
947 message_put(message);
948 relation = relation->next;
953 relation->type = RELATION_TYPE_SETUP;
954 relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new call */
955 relation->tx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
956 relation->rx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
957 /* create a new endpoint */
958 epoint = new Endpoint(0, c_serial);
961 remove_relation(relation);
962 goto ressource_error;
964 if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint)))
966 PERROR("ERROR:No endpoint's app.\n");
968 remove_relation(relation);
969 goto ressource_error;
971 relation->epoint_id = epoint->ep_serial;
972 /* send setup message to new endpoint */
973 //printf("JOLLY DEBUG: %d\n",call_countrelations(c_serial));
974 //i if (options.deb & DEBUG_CALL)
975 // callpbx_debug(call, "Call::message_epoint");
976 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, message_type);
977 memcpy(&message->param, param, sizeof(union parameter));
979 SCPY(message->param.setup.dialinginfo.id, newnumber);
980 PDEBUG(DEBUG_CALL, "setup message sent to ep %d with number='%s'.\n", relation->epoint_id, message->param.setup.dialinginfo.id);
981 message_put(message);