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()
242 struct call_relation *relation;
243 // char filename[256];
246 FATAL("epoint is NULL.\n");
248 PDEBUG(DEBUG_CALL, "creating new call and connecting it to the endpoint.\n");
250 c_type = CALL_TYPE_PBX;
252 c_caller_id[0] = '\0';
258 c_multicause = CAUSE_NOUSER;
259 c_multilocation = LOCATION_PRIVATE_LOCAL;
261 /* initialize a relation only to the calling interface */
262 relation = c_relation = (struct call_relation *)MALLOC(sizeof(struct call_relation));
264 relation->type = RELATION_TYPE_CALLING;
265 relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new call */
266 relation->tx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
267 relation->rx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
268 relation->epoint_id = epoint->ep_serial;
271 if (options.deb & DEBUG_CALL)
272 callpbx_debug(this, "CallPBX::Constructor(new call)");
281 struct call_relation *relation, *rtemp;
283 relation = c_relation;
286 rtemp = relation->next;
287 FREE(relation, sizeof(struct call_relation));
294 /* bridge sets the audio flow of all bchannels assiociated to 'this' call
295 * also it changes and notifies active/hold/conference states
297 void CallPBX::bridge(void)
299 struct call_relation *relation;
300 struct message *message;
301 int numconnect = 0, relations = 0;
302 class Endpoint *epoint;
303 struct port_list *portlist;
305 #ifdef DEBUG_COREBRIDGE
306 int allmISDN = 0; // never set for debug purpose
308 int allmISDN = 1; // set until a non-mISDN relation is found
311 relation = c_relation;
314 /* count all relations */
317 /* check for relation's objects */
318 epoint = find_epoint_id(relation->epoint_id);
321 PERROR("software error: relation without existing endpoints.\n");
322 relation = relation->next;
325 portlist = epoint->ep_portlist;
328 PDEBUG(DEBUG_CALL, "CALL%d ignoring relation without port object.\n", c_serial);
329 //#warning testing: keep on hold until single audio stream available
330 relation->channel_state = CHANNEL_STATE_HOLD;
331 relation = relation->next;
336 PDEBUG(DEBUG_CALL, "CALL%d ignoring relation with ep%d due to port_list.\n", c_serial, epoint->ep_serial);
337 //#warning testing: keep on hold until single audio stream available
338 relation->channel_state = CHANNEL_STATE_HOLD;
339 relation = relation->next;
342 port = find_port_id(portlist->port_id);
345 PDEBUG(DEBUG_CALL, "CALL%d ignoring relation without existing port object.\n", c_serial);
346 relation = relation->next;
349 if ((port->p_type&PORT_CLASS_MASK)!=PORT_CLASS_mISDN)
351 PDEBUG(DEBUG_CALL, "CALL%d ignoring relation ep%d because it's port is not mISDN.\n", c_serial, epoint->ep_serial);
354 PDEBUG(DEBUG_CALL, "CALL%d not all endpoints are mISDN.\n", c_serial);
357 relation = relation->next;
361 relation = relation->next;
364 PDEBUG(DEBUG_CALL, "CALL%d members=%d %s\n", c_serial, relations, (allmISDN)?"(all are mISDN-members)":"(not all are mISDN-members)");
365 /* we notify all relations about rxdata. */
366 relation = c_relation;
369 /* count connected relations */
370 if ((relation->channel_state == CHANNEL_STATE_CONNECT)
371 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
372 && (relation->rx_state != NOTIFY_STATE_HOLD))
375 /* remove unconnected parties from conference, also remove remotely disconnected parties so conference will not be disturbed. */
376 if (relation->channel_state == CHANNEL_STATE_CONNECT
377 && relation->rx_state != NOTIFY_STATE_HOLD
378 && relation->rx_state != NOTIFY_STATE_SUSPEND
379 && relations>1 // no conf with one member
380 && allmISDN) // no conf if any member is not mISDN
382 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
383 message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
384 message->param.mISDNsignal.conf = c_serial<<16 | c_pid;
385 PDEBUG(DEBUG_CALL, "CALL%d EP%d +on+ id: 0x%08x\n", c_serial, relation->epoint_id, message->param.mISDNsignal.conf);
386 message_put(message);
389 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
390 message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
391 message->param.mISDNsignal.conf = 0;
392 PDEBUG(DEBUG_CALL, "CALL%d EP%d +off+ id: 0x%08x\n", c_serial, relation->epoint_id, message->param.mISDNsignal.conf);
393 message_put(message);
397 * request data from endpoint/port if:
399 * - any without mISDN
400 * in this case we bridge
402 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
403 message->param.mISDNsignal.message = mISDNSIGNAL_CALLDATA;
404 message->param.mISDNsignal.calldata = (relations==2 && !allmISDN);
405 PDEBUG(DEBUG_CALL, "CALL%d EP%d set calldata=%d\n", c_serial, relation->epoint_id, message->param.mISDNsignal.calldata);
406 message_put(message);
408 relation = relation->next;
411 /* two people just exchange their states */
412 if (relations==2 && !c_partyline)
414 PDEBUG(DEBUG_CALL, "CALL%d 2 relations / no partyline\n", c_serial);
415 relation = c_relation;
416 relation->tx_state = notify_state_change(c_serial, relation->epoint_id, relation->tx_state, relation->next->rx_state);
417 relation->next->tx_state = notify_state_change(c_serial, relation->next->epoint_id, relation->next->tx_state, relation->rx_state);
419 /* one member in a call, so we put her on hold */
420 if (relations==1 || numconnect==1)
422 PDEBUG(DEBUG_CALL, "CALL%d 1 member or only 1 connected, put on hold\n");
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 PDEBUG(DEBUG_CALL, "CALL%d %d members, %d connected, signal conference\n", relations, numconnect);
436 relation = c_relation;
439 if ((relation->channel_state == CHANNEL_STATE_CONNECT)
440 && (relation->rx_state != NOTIFY_STATE_SUSPEND)
441 && (relation->rx_state != NOTIFY_STATE_HOLD))
442 relation->tx_state = notify_state_change(c_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_CONFERENCE);
443 relation = relation->next;
449 * bridging is only possible with two connected endpoints
451 void CallPBX::bridge_data(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param)
453 struct call_relation *relation_to;
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 destination endpoint has NOT audio mode CONNECT */
476 if (relation_to->channel_state != CHANNEL_STATE_CONNECT)
479 /* now we may send our data to the endpoint where it
480 * will be delivered to the port
482 //printf("from %d, to %d\n", relation_from->epoint_id, relation_to->epoint_id);
483 message_forward(c_serial, relation_to->epoint_id, CALL_TO_EPOINT, param);
486 /* release call from endpoint
487 * if the call has two relations, all relations are freed and the call will be
489 * on outgoing relations, the cause is collected, if not connected
490 * returns if call has been destroyed
492 int CallPBX::release(struct call_relation *relation, int location, int cause)
494 struct call_relation *reltemp, **relationpointer;
495 struct message *message;
499 /* remove from bridge */
500 if (relation->channel_state != CHANNEL_STATE_HOLD)
502 relation->channel_state = CHANNEL_STATE_HOLD;
503 c_updatebridge = 1; /* update bridge flag */
504 // note: if call is not released, bridge must be updated
507 /* detach given interface */
508 reltemp = c_relation;
509 relationpointer = &c_relation;
512 /* endpoint of function call */
513 if (relation == reltemp)
515 relationpointer = &reltemp->next;
516 reltemp = reltemp->next;
519 FATAL("relation not in list of our relations. this must not happen.\n");
520 *relationpointer = reltemp->next;
521 FREE(reltemp, sizeof(struct call_relation));
523 relation = reltemp = NULL; // just in case of reuse fault;
525 /* if no more relation */
528 PDEBUG(DEBUG_CALL, "call is completely removed.\n");
529 /* there is no more endpoint related to the call */
532 // end of call object!
533 PDEBUG(DEBUG_CALL, "call completely removed!\n");
535 /* if call is a party line */
538 PDEBUG(DEBUG_CALL, "call is a conference room, so we keep it alive until the last party left.\n");
540 /* if only one relation left */
541 if (!c_relation->next)
543 PDEBUG(DEBUG_CALL, "call has one relation left, so we send it a release with the given cause %d.\n", cause);
544 message = message_create(c_serial, c_relation->epoint_id, CALL_TO_EPOINT, MESSAGE_RELEASE);
545 message->param.disconnectinfo.cause = cause;
546 message->param.disconnectinfo.location = location;
547 message_put(message);
550 // end of call object!
551 PDEBUG(DEBUG_CALL, "call completely removed!\n");
557 if (options.deb & DEBUG_CALL && call->c_type==CALL_TYPE_PBX)
558 callpbx_debug((class CallPBX *)call, "call_release{all calls left}");
561 PDEBUG(DEBUG_CALL, "call_release(): ended.\n");
565 /* count number of relations in a call
567 int callpbx_countrelations(unsigned long call_id)
569 struct call_relation *relation;
572 class CallPBX *callpbx;
574 call = find_call_id(call_id);
579 if (call->c_type != CALL_TYPE_ASTERISK)
582 if (call->c_type != CALL_TYPE_PBX)
584 callpbx = (class CallPBX *)call;
587 relation = callpbx->c_relation;
591 relation = relation->next;
597 void CallPBX::remove_relation(struct call_relation *relation)
599 struct call_relation *temp, **tempp;
608 if (temp == relation)
615 PERROR("relation not in call.\n");
619 PDEBUG(DEBUG_CALL, "removing relation.\n");
620 *tempp = relation->next;
621 FREE(temp, sizeof(struct call_relation));
626 struct call_relation *CallPBX::add_relation(void)
628 struct call_relation *relation;
632 PERROR("there is no first relation to this call\n");
635 relation = c_relation;
636 while(relation->next)
637 relation = relation->next;
639 relation->next = (struct call_relation *)MALLOC(sizeof(struct call_relation));
641 /* the record pointer is set at the first time the data is received for the relation */
643 // if (options.deb & DEBUG_CALL)
644 // callpbx_debug(call, "add_relation");
645 return(relation->next);
648 /* epoint sends a message to a call
651 void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union parameter *param)
654 struct call_relation *relation, *reltemp;
657 struct message *message;
658 // int size, writesize, oldpointer;
659 char *number, *numbers;
663 PERROR("software error, epoint == NULL\n");
667 // if (options.deb & DEBUG_CALL)
669 // PDEBUG(DEBUG_CALL, "message %d received from ep%d.\n", message, epoint->ep_serial);
670 // callpbx_debug(call,"Call::message_epoint");
672 if (options.deb & DEBUG_CALL)
674 if (message_type != MESSAGE_DATA)
679 if (cl->c_type == CALL_TYPE_PBX)
680 callpbx_debug((class CallPBX *)cl, "Call::message_epoint{all calls before processing}");
687 relation = c_relation;
690 if (relation->epoint_id == epoint_id)
692 relation = relation->next;
696 PDEBUG(DEBUG_CALL, "no relation back to the endpoint found, ignoring (call=%d, endpoint=%d)\n", c_serial, epoint_id);
702 /* process channel message */
703 case MESSAGE_CHANNEL:
704 PDEBUG(DEBUG_CALL, "call received channel message: %d.\n", param->channel);
705 if (relation->channel_state != param->channel)
707 relation->channel_state = param->channel;
708 c_updatebridge = 1; /* update bridge flag */
709 if (options.deb & DEBUG_CALL)
710 callpbx_debug(this, "Call::message_epoint{after setting new channel state}");
716 switch(param->notifyinfo.notify)
718 case INFO_NOTIFY_USER_SUSPENDED:
719 case INFO_NOTIFY_USER_RESUMED:
720 case INFO_NOTIFY_REMOTE_HOLD:
721 case INFO_NOTIFY_REMOTE_RETRIEVAL:
722 case INFO_NOTIFY_CONFERENCE_ESTABLISHED:
723 case INFO_NOTIFY_CONFERENCE_DISCONNECTED:
724 new_state = track_notify(relation->rx_state, param->notifyinfo.notify);
725 if (new_state != relation->rx_state)
727 relation->rx_state = new_state;
729 if (options.deb & DEBUG_CALL)
730 callpbx_debug(this, "Call::message_epoint{after setting new rx state}");
735 /* send notification to all other endpoints */
736 reltemp = c_relation;
739 if (reltemp->epoint_id!=epoint_id && reltemp->epoint_id)
741 message = message_create(c_serial, reltemp->epoint_id, CALL_TO_EPOINT, MESSAGE_NOTIFY);
742 memcpy(&message->param, param, sizeof(union parameter));
743 message_put(message);
745 reltemp = reltemp->next;
752 /* now send audio data to the other endpoint */
753 bridge_data(epoint_id, relation, param);
756 /* relations sends a connect */
757 case MESSAGE_CONNECT:
758 /* outgoing setup type becomes connected */
759 if (relation->type == RELATION_TYPE_SETUP)
760 relation->type = RELATION_TYPE_CONNECT;
761 /* release other relations in setup state */
763 relation = c_relation;
766 if (relation->type == RELATION_TYPE_SETUP)
768 if (release(relation, LOCATION_PRIVATE_LOCAL, CAUSE_NONSELECTED))
769 return; // must return, because call IS destroyed
772 relation = relation->next;
774 break; // continue with our message
776 /* release is sent by endpoint */
777 case MESSAGE_RELEASE:
778 if (relation->type == RELATION_TYPE_SETUP)
780 /* collect cause and send collected cause */
781 collect_cause(&c_multicause, &c_multilocation, param->disconnectinfo.cause, param->disconnectinfo.location);
782 release(relation, c_multilocation, c_multicause);
785 /* send current cause */
786 release(relation, param->disconnectinfo.location, param->disconnectinfo.cause);
788 return; // must return, because call may be destroyed
791 /* process party line */
792 if (message_type == MESSAGE_SETUP) if (param->setup.partyline)
794 PDEBUG(DEBUG_CALL, "respsone with connect in partyline mode.\n");
795 c_partyline = param->setup.partyline;
796 message = message_create(c_serial, epoint_id, CALL_TO_EPOINT, MESSAGE_CONNECT);
797 message->param.setup.partyline = c_partyline;
798 message_put(message);
799 c_updatebridge = 1; /* update bridge flag */
803 if (message_type == MESSAGE_DISCONNECT)
805 PDEBUG(DEBUG_CALL, "releasing after receiving disconnect, because call in partyline mode.\n");
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);
815 PDEBUG(DEBUG_CALL, "ignoring message, because call in partyline mode.\n");
819 /* count relations */
820 num=callpbx_countrelations(c_serial);
822 /* check number of relations */
825 PDEBUG(DEBUG_CALL, "call has more than two relations so there is no need to send a message.\n");
829 /* find interfaces not related to calling epoint */
830 relation = c_relation;
833 if (relation->epoint_id != epoint_id)
835 relation = relation->next;
842 if (param->setup.dialinginfo.itype == INFO_ITYPE_ISDN_EXTENSION)
844 numbers = param->setup.dialinginfo.id;
845 while((number = strsep(&numbers, ",")))
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 bridge 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()))
942 FATAL("No memory for relation.\n");
943 relation->type = RELATION_TYPE_SETUP;
944 relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new call */
945 relation->tx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
946 relation->rx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
947 /* create a new endpoint */
948 epoint = new Endpoint(0, c_serial, 0);
950 FATAL("No memory for Endpoint instance\n");
951 if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint)))
952 FATAL("No memory for Endpoint Application instance\n");
953 relation->epoint_id = epoint->ep_serial;
954 /* send setup message to new endpoint */
955 //printf("JOLLY DEBUG: %d\n",call_countrelations(c_serial));
956 //i if (options.deb & DEBUG_CALL)
957 // callpbx_debug(call, "Call::message_epoint");
958 message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, message_type);
959 memcpy(&message->param, param, sizeof(union parameter));
961 SCPY(message->param.setup.dialinginfo.id, newnumber);
962 PDEBUG(DEBUG_CALL, "setup message sent to ep %d with number='%s'.\n", relation->epoint_id, message->param.setup.dialinginfo.id);
963 message_put(message);