From 701b046a45c2c79cc6d07ac3a4f84f499f7ed376 Mon Sep 17 00:00:00 2001 From: Super User Date: Thu, 26 Jul 2007 14:23:56 +0200 Subject: [PATCH] unified socket application interface (for asterisk and maybe other apps) bugfixes --- Makefile | 8 +- README | 3 +- action.cpp | 102 +++++++++++---- admin.h | 8 ++ admin_client.c | 35 ++++- admin_server.c | 153 +++++++++++++++------- admin_server.h | 6 +- apppbx.cpp | 132 +++++++++---------- apppbx.h | 6 +- asterisk_client.c | 26 +++- channel.c | 257 +++++++++++++++++++++++++++++++++++++ default/interface.conf | 20 ++- default/routing.conf | 2 + dss1.cpp | 8 +- dss1.h | 2 +- interface.c | 6 +- join.cpp | 8 +- join.h | 6 +- joinpbx.cpp | 178 ++++++++++++------------- joinpbx.h | 18 +-- joinasterisk.cpp => joinremote.cpp | 41 +++--- joinasterisk.h => joinremote.h | 11 +- mISDN.cpp | 56 ++++---- main.h | 2 +- message.h | 17 ++- route.c | 35 ++--- route.h | 9 +- todo.txt | 14 ++ trace.c | 2 +- 29 files changed, 817 insertions(+), 354 deletions(-) create mode 100644 channel.c rename joinasterisk.cpp => joinremote.cpp (60%) rename joinasterisk.h => joinremote.h (80%) diff --git a/Makefile b/Makefile index 71220e8..3fbf24b 100644 --- a/Makefile +++ b/Makefile @@ -130,8 +130,8 @@ join.o: join.cpp *.h Makefile joinpbx.o: joinpbx.cpp *.h Makefile $(CC) -c $(CFLAGS) joinpbx.cpp -o joinpbx.o -joinasterisk.o: joinasterisk.cpp *.h Makefile - $(CC) -c $(CFLAGS) joinasterisk.cpp -o joinasterisk.o +joinremote.o: joinremote.cpp *.h Makefile + $(CC) -c $(CFLAGS) joinremote.cpp -o joinremote.o cause.o: cause.c *.h Makefile $(CC) -c $(CFLAGS) cause.c -o cause.o @@ -182,7 +182,7 @@ $(LCR): main.o \ mail.o \ join.o \ joinpbx.o \ - joinasterisk.o \ + joinremote.o \ admin_server.o \ trace.o $(LD) $(LIBDIR) \ @@ -209,7 +209,7 @@ $(LCR): main.o \ mail.o \ join.o \ joinpbx.o \ - joinasterisk.o \ + joinremote.o \ admin_server.o \ trace.o \ $(LIBS) -o $(LCR) diff --git a/README b/README index 88994df..32193ca 100644 --- a/README +++ b/README @@ -351,7 +351,6 @@ Changes in Version 1.0 - Layer 1 over IP supports interconnection via IP - Rebuild line and b-channel hunting with individual lists - Screen lists for changing caller IDs -- Asterisk channel driver integrated - Multiplexing calls to multiple extensions - Removed all VoIP stuff to make core fast and stable (Use Asterisk for VoIP.) - Fixed a bug that caused some isdn connections to hang during disconnect @@ -359,4 +358,6 @@ Changes in Version 1.0 - Many minor improvements - New bugs of course... - Rename of 'Call' instances to 'Join', because they join parties together. +- A new remote interface for external applications is integrated + -> Our first application is (-: *ASTERISK CHANNEL DRIVER* :-) diff --git a/action.cpp b/action.cpp index d253679..d0dbf8d 100644 --- a/action.cpp +++ b/action.cpp @@ -67,9 +67,9 @@ char *numberrize_callerinfo(char *string, int ntype) /* - * process init 'internal' / 'external' / 'asterisk' / 'vbox-record' / 'partyline'... + * process init 'internal' / 'external' / 'remote' / 'vbox-record' / 'partyline'... */ -void EndpointAppPBX::_action_init_call(int asterisk) +void EndpointAppPBX::_action_init_call(char *remote) { class Join *join; struct port_list *portlist = ea_endpoint->ep_portlist; @@ -83,40 +83,80 @@ void EndpointAppPBX::_action_init_call(int asterisk) return; } - /* create call */ - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new call instance.\n", ea_endpoint->ep_serial); - if (asterisk) + /* create join */ + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new join instance.\n", ea_endpoint->ep_serial); + if (remote) { - admin = admin_list; + admin = admin_first; while(admin) { - if (admin->asterisk) + if (admin->remote[0] && !strcmp(admin->remote, remote)) break; admin = admin->next; } if (!admin) { /* resource not available */ + trace_header("ACTION remote (not available)", DIRECTION_NONE); + add_trace("application", NULL, "%s", remote); + end_trace(); message_disconnect_port(portlist, CAUSE_RESSOURCEUNAVAIL, LOCATION_PRIVATE_LOCAL, ""); new_state(EPOINT_STATE_OUT_DISCONNECT); set_tone(portlist,"cause_22"); return; } - join = new JoinAsterisk(ea_endpoint->ep_serial); + join = new JoinRemote(ea_endpoint->ep_serial, remote); } else join = new JoinPBX(ea_endpoint); if (!join) - FATAL("No memoy for Call instance.\n"); - ea_endpoint->ep_join_id = join->c_serial; + FATAL("No memoy for Join instance.\n"); + ea_endpoint->ep_join_id = join->j_serial; } void EndpointAppPBX::action_init_call(void) { - _action_init_call(0); + _action_init_call(NULL); } -void EndpointAppPBX::action_init_chan(void) +void EndpointAppPBX::action_init_remote(void) { - _action_init_call(1); + struct route_param *rparam; + struct port_list *portlist = ea_endpoint->ep_portlist; + struct message *message; + struct capa_info capainfo; + struct caller_info callerinfo; + struct redir_info redirinfo; + struct dialing_info dialinginfo; + char remote[32]; + + if (!(rparam = routeparam(e_action, PARAM_APPLICATION))) + { + trace_header("ACTION remote (no application given)", DIRECTION_NONE); + end_trace(); + new_state(EPOINT_STATE_OUT_DISCONNECT); + message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, ""); + set_tone(portlist, "cause_3f"); + return; + } + SCPY(remote, rparam->string_value); + _action_init_call(remote); + + /* create bearer/caller/dialinginfo */ + memcpy(&capainfo, &e_capainfo, sizeof(capainfo)); + memcpy(&callerinfo, &e_callerinfo, sizeof(callerinfo)); + memcpy(&redirinfo, &e_redirinfo, sizeof(redirinfo)); + memset(&dialinginfo, 0, sizeof(dialinginfo)); + + /* send setup to remote */ + trace_header("ACTION remote (setup)", DIRECTION_NONE); + add_trace("number", NULL, dialinginfo.id); + add_trace("remote", NULL, remote); + end_trace(); + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_SETUP); + memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info)); + memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info)); + memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info)); + memcpy(&message->param.setup.capainfo, &capainfo, sizeof(struct capa_info)); + message_put(message); } /* @@ -394,15 +434,25 @@ void EndpointAppPBX::action_dialing_external(void) } -void EndpointAppPBX::action_dialing_chan(void) +void EndpointAppPBX::action_dialing_remote(void) { - struct port_list *portlist = ea_endpoint->ep_portlist; + struct message *message; + struct dialing_info dialinginfo; +// struct route_param *rparam; - trace_header("ACTION channel (not implemented)", DIRECTION_NONE); - end_trace(); - message_disconnect_port(portlist, CAUSE_UNIMPLEMENTED, LOCATION_PRIVATE_LOCAL, ""); - new_state(EPOINT_STATE_OUT_DISCONNECT); - set_tone(portlist,"cause_4f"); + /* create bearer/caller/dialinginfo */ + memset(&dialinginfo, 0, sizeof(dialinginfo)); + + if (dialinginfo.id[0]) + { + /* add or update outgoing call */ + trace_header("ACTION remote (dialing)", DIRECTION_NONE); + add_trace("number", NULL, dialinginfo.id); + end_trace(); + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_INFORMATION); + memcpy(&message->param.information, &dialinginfo, sizeof(struct dialing_info)); + message_put(message); + } } @@ -526,10 +576,10 @@ void EndpointAppPBX::action_init_partyline(void) join = join_first; while(join) { - if (join->c_type == JOIN_TYPE_PBX) + if (join->j_type == JOIN_TYPE_PBX) { joinpbx = (class JoinPBX *)join; - if (joinpbx->c_partyline == rparam->integer_value) + if (joinpbx->j_partyline == rparam->integer_value) break; } join = join->next; @@ -553,7 +603,7 @@ void EndpointAppPBX::action_init_partyline(void) relation->epoint_id = ea_endpoint->ep_serial; } - ea_endpoint->ep_join_id = join->c_serial; + ea_endpoint->ep_join_id = join->j_serial; set_tone(portlist, "proceeding"); message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING); @@ -2318,10 +2368,10 @@ void EndpointAppPBX::process_dialing(void) goto process_action; } /* check for chan call */ - if (!strncmp(e_dialinginfo.id, "chan:", 5)) + if (!strncmp(e_dialinginfo.id, "remote:", 7)) { - e_extdialing = e_dialinginfo.id+4; - e_action = &action_chan; + e_extdialing = e_dialinginfo.id+7; + e_action = &action_remote; goto process_action; } /* check for vbox call */ diff --git a/admin.h b/admin.h index 70b21aa..a34820d 100644 --- a/admin.h +++ b/admin.h @@ -26,6 +26,7 @@ enum { /* messages */ ADMIN_RESPONSE_CMD_BLOCK, ADMIN_REQUEST_STATE, ADMIN_RESPONSE_STATE, + ADMIN_RESPONSE_S_REMOTE, ADMIN_RESPONSE_S_INTERFACE, ADMIN_RESPONSE_S_PORT, ADMIN_RESPONSE_S_EPOINT, @@ -55,6 +56,7 @@ struct admin_response_state { struct tm tm; char logfile[128]; int interfaces; + int remotes; int joins; int epoints; int ports; @@ -76,8 +78,13 @@ struct admin_response_interface { unsigned long port[256]; /* current port */ }; +struct admin_response_remote { + char name[32]; /* name of remote application */ +}; + struct admin_response_join { unsigned long serial; /* join serial number */ + char remote[32]; /* remote application name */ unsigned long partyline; }; @@ -153,6 +160,7 @@ struct admin_message { struct admin_response_port p; struct admin_response_epoint e; struct admin_response_join j; + struct admin_response_remote r; struct admin_call call; struct admin_msg msg; struct admin_trace_req trace_req; diff --git a/admin_client.c b/admin_client.c index a7e7f52..02624a0 100644 --- a/admin_client.c +++ b/admin_client.c @@ -405,6 +405,14 @@ int debug_join(struct admin_message *msg, struct admin_message *m, int line, int SPRINT(buffer, "%d\n", m[i].u.j.partyline); addstr(buffer); } + if (m[i].u.j.remote[0]) + { + color(cyan); + addstr(" remote="); + color(white); + SPRINT(buffer, "%s\n", m[i].u.j.remote); + addstr(buffer); + } /* find number of epoints */ j = msg->u.s.interfaces+msg->u.s.joins; jj = j + msg->u.s.epoints; @@ -485,7 +493,7 @@ char *admin_state(int sock, char *argv[]) cleanup_curses(); return("Response not valid. Expecting state response."); } - num = msg.u.s.interfaces + msg.u.s.joins + msg.u.s.epoints + msg.u.s.ports; + num = msg.u.s.interfaces + msg.u.s.remotes + msg.u.s.joins + msg.u.s.epoints + msg.u.s.ports; m = (struct admin_message *)MALLOC(num*sizeof(struct admin_message)); off=0; if (num) @@ -522,13 +530,25 @@ char *admin_state(int sock, char *argv[]) j++; } i = 0; + while(i < msg.u.s.remotes) + { + if (m[j].message != ADMIN_RESPONSE_S_REMOTE) + { + FREE(m, 0); + cleanup_curses(); + return("Response not valid. Expecting remote application information."); + } + i++; + j++; + } + i = 0; while(i < msg.u.s.joins) { if (m[j].message != ADMIN_RESPONSE_S_JOIN) { FREE(m, 0); cleanup_curses(); - return("Response not valid. Expecting call information."); + return("Response not valid. Expecting join information."); } i++; j++; @@ -763,6 +783,17 @@ char *admin_state(int sock, char *argv[]) i++; anything = 1; } + i = 0; + ii = i + msg.u.s.remotes; + while(i < ii) + { + /* show remote summary */ + move(++line>1?line:1, 0); + color(white); + SPRINT(buffer, "Remote: %s", m[i].u.r.name); + addstr(buffer); + i++; + } if (anything) line++; if (line+2 >= LINES) goto end; diff --git a/admin_server.c b/admin_server.c index 1176118..6292e12 100644 --- a/admin_server.c +++ b/admin_server.c @@ -33,7 +33,7 @@ char *socket_name = SOCKET_NAME; int sock = -1; struct sockaddr_un sock_address; -struct admin_list *admin_list = NULL; +struct admin_list *admin_first = NULL; /* * initialize admin socket @@ -86,7 +86,7 @@ int admin_init(void) /* * free connection - * also releases all asterisk joins + * also releases all remote joins */ void free_connection(struct admin_list *admin) { @@ -95,19 +95,19 @@ void free_connection(struct admin_list *admin) union parameter param; class Join *join, *joinnext; - /* free asterisk joins */ - if (admin->asterisk) + /* free remote joins */ + if (admin->remote[0]) { join = join_first; while(join) { joinnext = join->next; - if (join->c_type == JOIN_TYPE_ASTERISK) + if (join->j_type==JOIN_TYPE_REMOTE && !strcmp(((class JoinRemote *)join)->j_remote, admin->remote)) { memset(¶m, 0, sizeof(param)); param.disconnectinfo.cause = CAUSE_OUTOFORDER; param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; - ((class JoinAsterisk *)join)->message_asterisk(0, MESSAGE_RELEASE, ¶m); + ((class JoinRemote *)join)->message_remote(0, MESSAGE_RELEASE, ¶m); /* join is now destroyed, so we go to next join */ } join = joinnext; @@ -144,7 +144,7 @@ void admin_cleanup(void) { struct admin_list *admin, *next;; - admin = admin_list; + admin = admin_first; while(admin) { //printf("clean\n"); @@ -255,8 +255,8 @@ int admin_route(struct admin_queue **responsep) case ACTION_EXTERNAL: apppbx->e_action = &action_external; break; - case ACTION_CHAN: - apppbx->e_action = &action_chan; + case ACTION_REMOTE: + apppbx->e_action = &action_remote; break; case ACTION_VBOX_RECORD: apppbx->e_action = &action_vbox; @@ -552,7 +552,7 @@ void admin_call_response(int adminid, int message, char *connected, int cause, i /* searching for admin id * maybe there is no admin instance, because the calling port was not * initiated by admin_call */ - admin = admin_list; + admin = admin_first; while(admin) { if (adminid == admin->sockserial) @@ -591,85 +591,110 @@ void admin_call_response(int adminid, int message, char *connected, int cause, i /* - * send data to the asterisk join instance + * send data to the remote socket join instance */ -int admin_message_to_join(struct admin_msg *msg) +int admin_message_to_join(struct admin_msg *msg, char *remote) { class Join *join; struct admin_list *admin; - /* dummy callref means: asterisk is here */ + /* hello message */ if (msg->type == MESSAGE_HELLO) { - /* look for second asterisk */ - admin = admin_list; + if (remote[0]) + { + PERROR("Remote application repeats hello message.\n"); + return(-1); + } + /* look for second application */ + admin = admin_first; while(admin) { - if (admin->asterisk) + if (!strcmp(admin->remote, msg->param.hello.application)) break; admin = admin->next; } if (admin) { - PERROR("Asterisk connects twice??? (ignoring)\n"); + PERROR("Remote application connects twice??? (ignoring)\n"); return(-1); } /* set asterisk socket instance */ - admin->asterisk = 1; + SCPY(remote, msg->param.hello.application); + return(0); + } + + /* check we already have no application name */ + if (!remote[0]) + { + PERROR("Remote application did not send us a hello message.\n"); + return(-1); + } + + /* new join */ + if (msg->type == MESSAGE_NEWREF) + { + /* create new join instance */ + join = new JoinRemote(0, remote); // must have no serial, because no endpoint is connected + if (!join) + FATAL("No memory for remote join instance\n"); + return(0); + } + + /* check for ref */ + if (!msg->ref) + { + PERROR("Remote application did not send us a valid ref with a message.\n"); + return(-1); } /* find join instance */ join = join_first; while(join) { - if (join->c_serial == msg->ref) + if (join->j_serial == msg->ref) break; join = join->next; } - /* create join instance if not existing */ - if (!join) + /* check application */ + if (join->j_type != JOIN_TYPE_REMOTE) { - if (msg->ref < 2000000000) - { - PERROR("Asterisk sends us unknown ref %d below 2000000000.\n", msg->ref); - return(-1); - } - - /* create new join instance */ - join = new JoinAsterisk(0); // must have no serial, because no endpoint is connected - if (!join) - FATAL("No memory for Asterisk join instance\n"); + PERROR("Ref %d does not belong to a remote join instance.\n", msg->ref); + return(-1); + } + if (!!strcmp(remote, ((class JoinRemote *)join)->j_remote)) + { + PERROR("Ref %d belongs to remote application %s, but not to sending application %s.\n", msg->ref, ((class JoinRemote *)join)->j_remote, remote); + return(-1); } /* send message */ - if (join->c_type != JOIN_TYPE_ASTERISK) - FATAL("join instance %d must be of type join Asterisk\n", join->c_serial); - ((class JoinAsterisk *)join)->message_asterisk(msg->ref, msg->type, &msg->param); + ((class JoinRemote *)join)->message_remote(msg->ref, msg->type, &msg->param); return(0); } /* - * this function is called for every message to asterisk + * this function is called for every message to remote socket */ -int admin_message_from_join(unsigned long ref, int message_type, union parameter *param) +int admin_message_from_join(char *remote, unsigned long ref, int message_type, union parameter *param) { struct admin_list *admin; struct admin_queue *response, **responsep; /* response pointer */ /* searching for admin id - * maybe there is no asterisk instance + * maybe there is no given remote application */ - admin = admin_list; + admin = admin_first; while(admin) { - if (admin->asterisk) + if (admin->remote[0] && !strcmp(admin->remote, remote)) break; admin = admin->next; } - /* no asterisk connected */ + /* no given remote application connected */ if (!admin) return(-1); @@ -717,6 +742,7 @@ int admin_state(struct admin_queue **responsep) int num; int anybusy; struct admin_queue *response; + struct admin_list *admin; /* create state response */ response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); @@ -744,6 +770,16 @@ int admin_state(struct admin_queue **responsep) interface = interface->next; } response->am[0].u.s.interfaces = i; + /* remote connection count */ + i = 0; + admin = admin_first; + while(admin) + { + if (admin->remote[0]) + i++; + admin = admin->next; + } + response->am[0].u.s.remotes = i; /* join count */ join = join_first; i = 0; @@ -837,6 +873,22 @@ int admin_state(struct admin_queue **responsep) interface = interface->next; } + /* create response for all remotes */ + admin = admin_first; + while(admin) + { + if (admin->remote[0]) + { + /* message */ + response->am[num].message = ADMIN_RESPONSE_S_REMOTE; + /* name */ + SCPY(response->am[num].u.r.name, admin->remote); + /* */ + num++; + } + admin = admin->next; + } + /* create response for all joins */ join = join_first; while(join) @@ -844,10 +896,13 @@ int admin_state(struct admin_queue **responsep) /* message */ response->am[num].message = ADMIN_RESPONSE_S_JOIN; /* serial */ - response->am[num].u.j.serial = join->c_serial; + response->am[num].u.j.serial = join->j_serial; /* partyline */ - if (join->c_type == JOIN_TYPE_PBX) - response->am[num].u.j.partyline = ((class JoinPBX *)join)->c_partyline; + if (join->j_type == JOIN_TYPE_PBX) + response->am[num].u.j.partyline = ((class JoinPBX *)join)->j_partyline; + /* remote application */ + if (join->j_type == JOIN_TYPE_REMOTE) + SCPY(response->am[num].u.j.remote, ((class JoinRemote *)join)->j_remote); /* */ join = join->next; num++; @@ -1029,8 +1084,8 @@ int admin_handle(void) memuse++; fhuse++; admin->sockserial = sockserial++; - admin->next = admin_list; - admin_list = admin; + admin->next = admin_first; + admin_first = admin; admin->sock = new_sock; } else { close(new_sock); @@ -1047,8 +1102,8 @@ int admin_handle(void) } /* loop all current socket connections */ - admin = admin_list; - adminp = &admin_list; + admin = admin_first; + adminp = &admin_first; while(admin) { /* read command */ @@ -1091,7 +1146,7 @@ int admin_handle(void) *adminp = admin->next; free_connection(admin); admin = *adminp; -//PERROR("DEBUG (admin_list=%x)\n", admin_list); +//PERROR("DEBUG (admin_first=%x)\n", admin_first); continue; } if (len != sizeof(msg)) @@ -1170,7 +1225,7 @@ int admin_handle(void) break; case ADMIN_MESSAGE: - if (admin_message_to_join(&msg.u.msg) < 0) + if (admin_message_to_join(&msg.u.msg, admin->remote) < 0) { PERROR("Failed to deliver message for socket %d.\n", admin->sock); goto response_error; diff --git a/admin_server.h b/admin_server.h index d83c451..2351298 100644 --- a/admin_server.h +++ b/admin_server.h @@ -22,19 +22,19 @@ struct admin_list { struct admin_list *next; int sock; int sockserial; - int asterisk; /* socket is connected to asterisk */ + char remote[32]; /* socket is connected remote application */ struct admin_trace_req trace; /* stores trace, if detail != 0 */ unsigned long epointid; struct admin_queue *response; }; -extern struct admin_list *admin_list; +extern struct admin_list *admin_first; int admin_init(void); void admin_cleanup(void); int admin_handle(void); void admin_call_response(int adminid, int message, char *connected, int cause, int location, int notify); int admin_message_to_join(struct admin_message *msg); -int admin_message_from_join(unsigned long ref, int message_type, union parameter *param); +int admin_message_from_join(char *remote, unsigned long ref, int message_type, union parameter *param); diff --git a/apppbx.cpp b/apppbx.cpp index 7dbf24e..1aeba78 100644 --- a/apppbx.cpp +++ b/apppbx.cpp @@ -1477,8 +1477,8 @@ int EndpointAppPBX::handler(void) ea_endpoint->free_portlist(portlist); } /* put on hold */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_HOLD; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_HOLD; message_put(message); /* indicate no patterns */ message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN); @@ -1994,8 +1994,8 @@ void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, message_put(message); /* connect audio, if not already */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_CONNECT; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_CONNECT; message_put(message); } else { @@ -2004,8 +2004,8 @@ void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, message_put(message); /* disconnect audio, if not already */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_HOLD; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_HOLD; message_put(message); } new_state(EPOINT_STATE_OUT_OVERLAP); @@ -2037,8 +2037,8 @@ void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_typ message_put(message); /* connect audio, if not already */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_CONNECT; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_CONNECT; message_put(message); } else { @@ -2047,8 +2047,8 @@ void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_typ message_put(message); /* disconnect audio, if not already */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_HOLD; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_HOLD; message_put(message); } /* if we are in a call */ @@ -2079,8 +2079,8 @@ void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, message_put(message); /* connect audio, if not already */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_CONNECT; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_CONNECT; message_put(message); } else { @@ -2089,8 +2089,8 @@ void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, message_put(message); /* disconnect audio, if not already */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_HOLD; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_HOLD; message_put(message); } /* if we are in a call */ @@ -2213,8 +2213,8 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, } if (ea_endpoint->ep_join_id) { - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_CONNECT; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_CONNECT; message_put(message); } else if (!e_adminid) { @@ -2406,8 +2406,8 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN); message_put(message); /* connect audio, if not already */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_CONNECT; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_CONNECT; message_put(message); /* send disconnect */ message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type); @@ -2540,8 +2540,8 @@ void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, u /* tell call about it */ if (ea_endpoint->ep_join_id) { - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_HOLD; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_HOLD; message_put(message); } break; @@ -2565,8 +2565,8 @@ void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, u /* tell call about it */ if (ea_endpoint->ep_join_id) { - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_CONNECT; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_CONNECT; message_put(message); } break; @@ -2971,8 +2971,8 @@ void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, if (e_join_pattern && e_ext.own_setup) { /* disconnect audio */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_HOLD; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_HOLD; message_put(message); } if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) @@ -2997,11 +2997,11 @@ void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_typ if (e_join_pattern) { /* connect / disconnect audio */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); if (e_ext.own_proceeding) - message->param.channel = CHANNEL_STATE_HOLD; + message->param.audiopath = CHANNEL_STATE_HOLD; else - message->param.channel = CHANNEL_STATE_CONNECT; + message->param.audiopath = CHANNEL_STATE_CONNECT; message_put(message); } // UCPY(e_join_tone, "proceeding"); @@ -3025,11 +3025,11 @@ void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, if (e_join_pattern) { /* connect / disconnect audio */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); if (e_ext.own_alerting) - message->param.channel = CHANNEL_STATE_HOLD; + message->param.audiopath = CHANNEL_STATE_HOLD; else - message->param.channel = CHANNEL_STATE_CONNECT; + message->param.audiopath = CHANNEL_STATE_CONNECT; message_put(message); } if (portlist) @@ -3109,8 +3109,8 @@ void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, } set_tone(portlist, NULL); e_join_pattern = 0; - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_CONNECT; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_CONNECT; message_put(message); e_start = now; } @@ -3213,8 +3213,8 @@ void EndpointAppPBX::join_disconnect_release(struct port_list *portlist, int mes e_join_pattern = 0; } else /* else we enable audio */ { - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_CONNECT; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_CONNECT; message_put(message); } /* send disconnect message */ @@ -3254,8 +3254,8 @@ void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, un } /* disconnect audio */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_HOLD; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_HOLD; message_put(message); /* get dialing info */ @@ -3564,12 +3564,12 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un portlist = portlist->next; } /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_CONNECT; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_CONNECT; message_put(message); // /* tell remote epoint to connect audio also, because we like to hear the patterns */ // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_REMOTE_AUDIO); -// message->param.channel = CHANNEL_STATE_CONNECT; +// message->param.audiopath = CHANNEL_STATE_CONNECT; // message_put(message); // patterns are available, remote already connected audio } @@ -3583,8 +3583,8 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n"); e_join_pattern = 0; /* disconnect our audio tx and rx */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_HOLD; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_HOLD; message_put(message); } break; @@ -3593,8 +3593,8 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un /* CALL (dunno at the moment) */ case MESSAGE_REMOTE_AUDIO: PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received audio remote request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id); - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = param->channel; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = param->channel; message_put(message); break; #endif @@ -3725,13 +3725,13 @@ reject: PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial); goto reject; } - if (joinpbx->c_type != JOIN_TYPE_PBX) + if (joinpbx->j_type != JOIN_TYPE_PBX) { PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial); goto reject; } joinpbx = (class JoinPBX *)join; - relation = joinpbx->c_relation; + relation = joinpbx->j_relation; if (!relation) { PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial); @@ -3760,7 +3760,7 @@ reject: PDEBUG(DEBUG_EPOINT, "showing all joins:\n"); while(debug_c) { - PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->c_serial); + PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial); debug_c = debug_c->next; } PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n"); @@ -3816,12 +3816,12 @@ reject: message_put(message); /* we send a connect to the audio path (not for vbox) */ - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL); - message->param.channel = CHANNEL_STATE_CONNECT; + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH); + message->param.audiopath = CHANNEL_STATE_CONNECT; message_put(message); /* beeing paranoid, we make call update */ - joinpbx->c_updatebridge = 1; + joinpbx->j_updatebridge = 1; if (options.deb & DEBUG_EPOINT) { @@ -3834,7 +3834,7 @@ reject: PDEBUG(DEBUG_EPOINT, "showing all joins:\n"); while(debug_c) { - PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->c_serial); + PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial); debug_c = debug_c->next; } PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n"); @@ -3873,7 +3873,7 @@ void EndpointAppPBX::join_join(void) PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial); return; } - if (our_join->c_type != JOIN_TYPE_PBX) + if (our_join->j_type != JOIN_TYPE_PBX) { PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial); return; @@ -3958,21 +3958,21 @@ void EndpointAppPBX::join_join(void) PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial); return; } - if (other_join->c_type != JOIN_TYPE_PBX) + if (other_join->j_type != JOIN_TYPE_PBX) { PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial); return; } other_joinpbx = (class JoinPBX *)other_join; - if (our_joinpbx->c_partyline && other_joinpbx->c_partyline) + if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) { PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial); return; } /* remove relation to endpoint for join on hold */ - other_relation = other_joinpbx->c_relation; - other_relation_pointer = &other_joinpbx->c_relation; + other_relation = other_joinpbx->j_relation; + other_relation_pointer = &other_joinpbx->j_relation; while(other_relation) { if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial) @@ -3990,8 +3990,8 @@ void EndpointAppPBX::join_join(void) temp_epoint = find_epoint_id(other_relation->epoint_id); if (temp_epoint) { - if (temp_epoint->ep_join_id == other_join->c_serial) - temp_epoint->ep_join_id = our_join->c_serial; + if (temp_epoint->ep_join_id == other_join->j_serial) + temp_epoint->ep_join_id = our_join->j_serial; } other_relation_pointer = &other_relation->next; @@ -4000,32 +4000,32 @@ void EndpointAppPBX::join_join(void) PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial); /* join call relations */ - our_relation = our_joinpbx->c_relation; - our_relation_pointer = &our_joinpbx->c_relation; + our_relation = our_joinpbx->j_relation; + our_relation_pointer = &our_joinpbx->j_relation; while(our_relation) { our_relation_pointer = &our_relation->next; our_relation = our_relation->next; } - *our_relation_pointer = other_joinpbx->c_relation; - other_joinpbx->c_relation = NULL; + *our_relation_pointer = other_joinpbx->j_relation; + other_joinpbx->j_relation = NULL; PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial); /* release endpoint on hold */ - message = message_create(other_joinpbx->c_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE); + message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE); message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */ message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; message_put(message); /* if we are not a partyline, we get partyline state from other join */ - our_joinpbx->c_partyline += other_joinpbx->c_partyline; + our_joinpbx->j_partyline += other_joinpbx->j_partyline; /* remove empty join */ delete other_join; PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n"); /* mixer must update */ - our_joinpbx->c_updatebridge = 1; /* update mixer flag */ + our_joinpbx->j_updatebridge = 1; /* update mixer flag */ /* we send a retrieve to that endpoint */ // mixer will update the hold-state of the join and send it to the endpoints is changes @@ -4064,14 +4064,14 @@ int EndpointAppPBX::check_external(char **errstr, class Port **port) *errstr = "No Call"; return(1); } - if (join->c_type != JOIN_TYPE_PBX) + if (join->j_type != JOIN_TYPE_PBX) { PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial); *errstr = "No PBX Call"; return(1); } joinpbx = (class JoinPBX *)join; - relation = joinpbx->c_relation; + relation = joinpbx->j_relation; if (!relation) { PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial); diff --git a/apppbx.h b/apppbx.h index c93f38c..43404f9 100644 --- a/apppbx.h +++ b/apppbx.h @@ -249,13 +249,13 @@ class EndpointAppPBX : public EndpointApp struct route_param *routeparam(struct route_action *action, unsigned long long id); /* init / dialing / hangup */ - void _action_init_call(int chan); + void _action_init_call(char *remote); void action_init_call(void); - void action_init_chan(void); + void action_init_remote(void); void action_dialing_internal(void); void action_dialing_external(void); void action_dialing_h323(void); - void action_dialing_chan(void); + void action_dialing_remote(void); void action_dialing_vbox_record(void); void action_init_partyline(void); void action_hangup_call(void); diff --git a/asterisk_client.c b/asterisk_client.c index def6545..13ab261 100644 --- a/asterisk_client.c +++ b/asterisk_client.c @@ -9,6 +9,25 @@ ** ** \*****************************************************************************/ +/* + +How does it work: + +To connect, open a socket and send a MESSAGE_HELLO to admin socket with +the application name. This name is unique an can be used for routing calls. + +To make a call, send a MESSAGE_NEWREF and a new reference is received. +When receiving a call, a new reference is received. +The reference is received with MESSAGE_NEWREF. + +Make a MESSAGE_SETUP or receive a MESSAGE_SETUP with the reference. + +To release call and reference, send or receive MESSAGE_RELEASE. +From that point on, the ref is not valid, so no other message may be sent +with that reference. + +*/ + #include #include #include @@ -138,7 +157,7 @@ int main(int argc, char *argv[]) struct sockaddr_un sock_address; int ret; unsigned long on = 1; - union parameter hello_param; + union parameter param; /* open socket */ if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) @@ -169,8 +188,9 @@ int main(int argc, char *argv[]) } /* enque hello message */ - memset(&hello_param, 0, sizeof(hello_param)); - admin_asterisk(MESSAGE_HELLO, &hello_param); + memset(¶m, 0, sizeof(param)); + SCPY(param.hello.application, "asterisk"); + admin_asterisk(MESSAGE_HELLO, ¶m); while(42) { diff --git a/channel.c b/channel.c new file mode 100644 index 0000000..56d9e0d --- /dev/null +++ b/channel.c @@ -0,0 +1,257 @@ +/*****************************************************************************\ +** ** +** Linux Call Router ** +** ** +**---------------------------------------------------------------------------** +** Copyright: Andreas Eversberg ** +** ** +** mISDN bchannel access (for Asterisk) ** +** ** +\*****************************************************************************/ + + +#include +#include +#include +#include "main.h" +#include +#include +#include +#include +#include +#include +#include +extern "C" { +#include +} + +#if 0 +#ifndef ISDN_PID_L2_B_USER +#define ISDN_PID_L2_B_USER 0x420000ff +#endif +#ifndef ISDN_PID_L3_B_USER +#define ISDN_PID_L3_B_USER 0x430000ff +#endif +#endif +#ifndef ISDN_PID_L4_B_USER +#define ISDN_PID_L4_B_USER 0x440000ff +#endif + +/* used for udevice */ +int entity = 0; + +/* the device handler and port list */ +int mISDNdevice = -1; + + +/* open mISDN device */ +void mISDNdevice_open(void) +{ + /* open mISDNdevice if not already open */ + if (mISDNdevice < 0) + { + ret = mISDN_open(); + if (ret < 0) + { + PERROR("cannot open mISDN device ret=%d errno=%d (%s) Check for mISDN modules!\nAlso did you create \"/dev/mISDN\"? Do: \"mknod /dev/mISDN c 46 0\"\n", ret, errno, strerror(errno)); + return(NULL); + } + mISDNdevice = ret; + PDEBUG(DEBUG_ISDN, "mISDN device opened.\n"); + } +} + +/* close mISDN device */ +void mISDNdevice_close(void) +{ + if (mISDNdevice > -1) + { + mISDN_close(); + PDEBUG(DEBUG_ISDN, "mISDN device closed.\n"); + } +} + +/* create bchannel layer */ +unsigned long mISDN_createlayer(unsigned long stid) +{ + unsigned long addr; + + /* create new layer */ + PDEBUG(DEBUG_BCHANNEL, "creating new layer for bchannel stid=0%x.\n" , stid); + memset(&li, 0, sizeof(li)); + memset(&pid, 0, sizeof(pid)); + li.object_id = -1; + li.extentions = 0; + li.st = stid; + UCPY(li.name, "B L4"); + li.pid.layermask = ISDN_LAYER((4)); + li.pid.protocol[4] = ISDN_PID_L4_B_USER; + ret = mISDN_new_layer(mISDNdevice, &li); + if (ret) + { + failed_new_layer: + PERROR("mISDN_new_layer() failed to add bchannel stid=0%x.\n", stid); + goto failed; + } + addr = li.id; + if (!li.id) + { + goto failed_new_layer; + } + PDEBUG(DEBUG_BCHANNEL, "new layer (addr=0x%x)\n", addr); + + /* create new stack */ + pid.protocol[1] = ISDN_PID_L1_B_64TRANS; + pid.protocol[2] = ISDN_PID_L2_B_TRANS; + pid.protocol[3] = ISDN_PID_L3_B_DSP; + pid.protocol[4] = ISDN_PID_L4_B_USER; + pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4)); + ret = mISDN_set_stack(mISDNdevice, stid, &pid); + if (ret) + { + stack_error: + PERROR("mISDN_set_stack() failed (ret=%d) to add bchannel stid=0x%x\n", ret, stid); + mISDN_write_frame(mISDNdevice, buff, addr, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); + goto failed; + } + ret = mISDN_get_setstack_ind(mISDNdevice, addr); + if (ret) + goto stack_error; + + /* get layer id */ + addr = mISDN_get_layerid(mISDNdevice, stid, 4); + if (!addr) + goto stack_error; +} + +/* destroy bchannel layer */ +void mISDN_destroylayer(unsigned long stid, unsigned long addr) +{ + /* remove our stack only if set */ + if (addr) + { + PDEBUG(DEBUG_BCHANNEL, "free stack (addr=0x%x)\n", addr); + mISDN_clear_stack(mISDNdevice, stid); + mISDN_write_frame(mISDNdevice, buff, addr | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); + } +} + +/* do activation and deactivation of bchannel */ +static void mISDN_bchannelactivate(unsigned long addr, int activate) +{ + iframe_t act; + + /* activate bchannel */ + act.prim = (activate?DL_ESTABLISH:DL_RELEASE) | REQUEST; + act.addr = addr | FLG_MSG_DOWN; + act.dinfo = 0; + act.len = 0; + mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC); +} + +/* handle all mISDN messages */ +int mISDN_handler(void) +{ + int ret; + msg_t *msg; + iframe_t *frm; + struct mISDNport *mISDNport; + class PmISDN *isdnport; + net_stack_t *nst; + msg_t *dmsg; + mISDNuser_head_t *hh; + int i; + + /* no device, no read */ + if (mISDNdevice < 0) + return(0); + + /* get message from kernel */ + if (!(msg = alloc_msg(MAX_MSG_SIZE))) + return(1); + ret = mISDN_read(mISDNdevice, msg->data, MAX_MSG_SIZE, 0); + if (ret < 0) + { + free_msg(msg); + if (errno == EAGAIN) + return(0); + FATAL("Failed to do mISDN_read()\n"); + } + if (!ret) + { + free_msg(msg); +// printf("%s: ERROR: mISDN_read() returns nothing\n"); + return(0); + } + msg->len = ret; + frm = (iframe_t *)msg->data; + + /* global prim */ + switch(frm->prim) + { + case MGR_DELLAYER | CONFIRM: + case MGR_INITTIMER | CONFIRM: + case MGR_ADDTIMER | CONFIRM: + case MGR_DELTIMER | CONFIRM: + case MGR_REMOVETIMER | CONFIRM: + free_msg(msg); + return(1); + } + + /* look for channel instance, that has the address of this message */ + chan = chan_first; + while(chan) + { + if (frm->addr == chan->b_addr) + break; + chan = chan->next; + } + if (!chan) + { + PERROR("message belongs to no chan: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len); + goto out; + } + + /* b-message */ + switch(frm->prim) + { + /* we don't care about confirms, we use rx data to sync tx */ + case PH_DATA | CONFIRM: + case DL_DATA | CONFIRM: + break; + + /* we receive audio data, we respond to it AND we send tones */ + case PH_DATA | INDICATION: + case DL_DATA | INDICATION: + case PH_CONTROL | INDICATION: + i = 0; + chan->bchannel_receive(frm); + break; + + case PH_ACTIVATE | INDICATION: + case DL_ESTABLISH | INDICATION: + case PH_ACTIVATE | CONFIRM: + case DL_ESTABLISH | CONFIRM: + PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr); + chan->b_active = 1; + bchannel_event(mISDNport, i, B_EVENT_ACTIVATED); + break; + + case PH_DEACTIVATE | INDICATION: + case DL_RELEASE | INDICATION: + case PH_DEACTIVATE | CONFIRM: + case DL_RELEASE | CONFIRM: + PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr); + chan->b_active = 0; + bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED); + break; + + default: + PERROR("child message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len); + } + + out: + free_msg(msg); + return(1); +} + diff --git a/default/interface.conf b/default/interface.conf index 6df206c..07bc818 100644 --- a/default/interface.conf +++ b/default/interface.conf @@ -57,8 +57,8 @@ # Also this interface will connect bchannel during call setup, so tones are # required. #[Ext] -#screen_out unknown 300 national 21250993300 -#screen_out unknown 2* national 212509932* +#screen-out unknown 300 national 21250993300 +#screen-out unknown 2* national 212509932* #tones yes #port 1 @@ -67,11 +67,23 @@ # 10 channels (channel 1-10) are incomming only. # 10 channels (channel 11-15,17-21) are outgoing only. # 10 channels (channel 22-31) are both way. -# We prefer to use directed channels first, then we request any channel: +# We prefer to use directed channels first, then we request any channel. +# Outgoing calls on both-way-channels shall be indicated as "any channel". +# (Siemens EWSD will select bot-way-channels when indicated that way.) #[Ext] #port 1 -#channel force,11,12,13,14,15,17,18,19,20,21,any +#channel-in 1,2,3,4,5,6,7,8,9,10,22,23,24,25,26,27,28,29,30,31 +#channel-out force,11,12,13,14,15,17,18,19,20,21,any + +# Example of an ISDN interface that runs in NT-mode, but provides tones during +# setup. Also we provide tones during setup also. +# This is usefull to interconnect to another PBX. +#[PBX] +#port 5 +#earlyb yes +#tones yes +# Hint: Enter "lcr interface" for quick help on interface options. # Add your interfaces here: diff --git a/default/routing.conf b/default/routing.conf index 0e2aaac..38e739a 100644 --- a/default/routing.conf +++ b/default/routing.conf @@ -5,6 +5,7 @@ # Calls with different origins will be processed in different rulesets. [main] +#interface=xyz : goto ruleset=xyz extern : goto ruleset=extern intern : goto ruleset=intern : disconnect cause=31 @@ -13,6 +14,7 @@ intern : goto ruleset=intern # All calls from external lines are processed here. [extern] +dialing=1234 remote=asterisk : remote application=asterisk dialing=0,1234 : intern extension=200 dialing=200-299 : intern dialing=81 : partyline room=42 diff --git a/dss1.cpp b/dss1.cpp index 8f23c74..6aff417 100644 --- a/dss1.cpp +++ b/dss1.cpp @@ -812,7 +812,7 @@ void Pdss1::setup_acknowledge_ind(unsigned long prim, unsigned long dinfo, void end_trace(); /* process channel */ - ret = received_first_reply_to_setup(prim, exclusive, channel); + ret = received_first_reply_to_setup(prim, channel, exclusive); if (ret < 0) { message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE); @@ -849,7 +849,7 @@ void Pdss1::proceeding_ind(unsigned long prim, unsigned long dinfo, void *data) dec_ie_redir_dn(proceeding->REDIR_DN, (Q931_info_t *)((unsigned long)data+headerlen), &type, &plan, &present, (unsigned char *)redir, sizeof(redir)); end_trace(); - ret = received_first_reply_to_setup(prim, exclusive, channel); + ret = received_first_reply_to_setup(prim, channel, exclusive); if (ret < 0) { message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE); @@ -933,7 +933,7 @@ void Pdss1::alerting_ind(unsigned long prim, unsigned long dinfo, void *data) end_trace(); /* process channel */ - ret = received_first_reply_to_setup(prim, exclusive, channel); + ret = received_first_reply_to_setup(prim, channel, exclusive); if (ret < 0) { message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE); @@ -1024,7 +1024,7 @@ void Pdss1::connect_ind(unsigned long prim, unsigned long dinfo, void *data) /* select channel */ bchannel_before = p_m_b_channel; - ret = received_first_reply_to_setup(prim, exclusive, channel); + ret = received_first_reply_to_setup(prim, channel, exclusive); if (ret < 0) { message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE); diff --git a/dss1.h b/dss1.h index 93f0865..488e56b 100644 --- a/dss1.h +++ b/dss1.h @@ -30,7 +30,7 @@ class Pdss1 : public PmISDN void new_state(int state); /* set new state */ void isdn_show_send_message(unsigned long prim, msg_t *msg); - int received_first_reply_to_setup(unsigned long prim, int exclusive, int channel); + int received_first_reply_to_setup(unsigned long prim, int channel, int exclusive); int hunt_bchannel(int exclusive, int channel); void information_ind(unsigned long prim, unsigned long dinfo, void *data); void setup_ind(unsigned long prim, unsigned long dinfo, void *data); diff --git a/interface.c b/interface.c index 1a17842..fa7270d 100644 --- a/interface.c +++ b/interface.c @@ -668,7 +668,7 @@ struct interface_param interface_param[] = { "This is required on PRI NT-mode ports that are point-to-point by default.\n" "This parameter must follow a 'port' parameter."}, - {"channel_out", &inter_channel_out, "[force,][][,...][,free][,any][,no]", + {"channel-out", &inter_channel_out, "[force,][][,...][,free][,any][,no]", "Channel selection list for all outgoing calls to the interface.\n" "A free channels is searched in order of appearance.\n" "This parameter must follow a 'port' parameter.\n" @@ -678,10 +678,10 @@ struct interface_param interface_param[] = { " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n" " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"}, - {"channel_in", &inter_channel_in, "[force,][][,...][,free][,any][,no]", + {"channel-in", &inter_channel_in, "[force,][][,...][,free][,any][,no]", "Channel selection list for all incomming calls from the interface.\n" "A free channels is accepted if in the list.\n" - "If no channel was requested, the first free channel found is selected.\n" + "If any channel was requested, the first free channel found is selected.\n" "This parameter must follow a 'port' parameter.\n" " [,...] - List of channels to accept.\n" " free - Accept any free channel"}, diff --git a/join.cpp b/join.cpp index 2a1e0a7..df7bf67 100644 --- a/join.cpp +++ b/join.cpp @@ -38,8 +38,8 @@ class Join *find_join_id(unsigned long join_id) while(join) { -//printf("comparing: '%s' with '%s'\n", name, join->c_name); - if (join->c_serial == join_id) +//printf("comparing: '%s' with '%s'\n", name, join->j_name); + if (join->j_serial == join_id) return(join); join = join->next; } @@ -55,8 +55,8 @@ Join::Join(void) { class Join **joinp; - c_serial = join_serial++; - c_type = JOIN_TYPE_NONE; + j_serial = join_serial++; + j_type = JOIN_TYPE_NONE; /* attach to chain */ next = NULL; diff --git a/join.h b/join.h index 8c255cc..9ef2d1d 100644 --- a/join.h +++ b/join.h @@ -9,7 +9,7 @@ ** ** \*****************************************************************************/ -enum { JOIN_TYPE_NONE, JOIN_TYPE_PBX, JOIN_TYPE_ASTERISK}; +enum { JOIN_TYPE_NONE, JOIN_TYPE_PBX, JOIN_TYPE_REMOTE}; /* join * @@ -26,8 +26,8 @@ class Join virtual void message_epoint(unsigned long epoint_id, int message, union parameter *param); virtual int handler(void); - unsigned long c_type; /* join type (pbx or asterisk) */ - unsigned long c_serial; /* serial/unique number of join */ + unsigned long j_type; /* join type (pbx or asterisk) */ + unsigned long j_serial; /* serial/unique number of join */ }; void join_free(void); diff --git a/joinpbx.cpp b/joinpbx.cpp index 9f8f533..552352f 100644 --- a/joinpbx.cpp +++ b/joinpbx.cpp @@ -132,9 +132,9 @@ void joinpbx_debug(class JoinPBX *joinpbx, char *function) if (!(options.deb & DEBUG_JOIN)) return; - PDEBUG(DEBUG_JOIN, "join(%d) start (called from %s)\n", joinpbx->c_serial, function); + PDEBUG(DEBUG_JOIN, "join(%d) start (called from %s)\n", joinpbx->j_serial, function); - relation = joinpbx->c_relation; + relation = joinpbx->j_relation; if (!relation) PDEBUG(DEBUG_JOIN, "join has no relations\n"); @@ -160,8 +160,8 @@ void joinpbx_debug(class JoinPBX *joinpbx, char *function) UPRINT(strchr(buffer,0), ",", portlist->port_id); portlist = portlist->next; } -// UPRINT(strchr(buffer,0), " endpoint=%d on=%s hold=%s", epoint->ep_serial, (epoint->ep_join_id==joinpbx->c_serial)?"yes":"no", (epoint->get_hold_id()==joinpbx->c_serial)?"yes":"no"); - UPRINT(strchr(buffer,0), " endpoint=%d on=%s", epoint->ep_serial, (epoint->ep_join_id==joinpbx->c_serial)?"yes":"no"); +// UPRINT(strchr(buffer,0), " endpoint=%d on=%s hold=%s", epoint->ep_serial, (epoint->ep_join_id==joinpbx->j_serial)?"yes":"no", (epoint->get_hold_id()==joinpbx->j_serial)?"yes":"no"); + UPRINT(strchr(buffer,0), " endpoint=%d on=%s", epoint->ep_serial, (epoint->ep_join_id==joinpbx->j_serial)?"yes":"no"); switch(relation->type) { case RELATION_TYPE_CALLING: @@ -247,19 +247,19 @@ JoinPBX::JoinPBX(class Endpoint *epoint) : Join() PDEBUG(DEBUG_JOIN, "creating new join and connecting it to the endpoint.\n"); - c_type = JOIN_TYPE_PBX; - c_caller[0] = '\0'; - c_caller_id[0] = '\0'; - c_dialed[0] = '\0'; - c_todial[0] = '\0'; - c_pid = getpid(); - c_updatebridge = 0; - c_partyline = 0; - c_multicause = CAUSE_NOUSER; - c_multilocation = LOCATION_PRIVATE_LOCAL; + j_type = JOIN_TYPE_PBX; + j_caller[0] = '\0'; + j_caller_id[0] = '\0'; + j_dialed[0] = '\0'; + j_todial[0] = '\0'; + j_pid = getpid(); + j_updatebridge = 0; + j_partyline = 0; + j_multicause = CAUSE_NOUSER; + j_multilocation = LOCATION_PRIVATE_LOCAL; /* initialize a relation only to the calling interface */ - relation = c_relation = (struct join_relation *)MALLOC(sizeof(struct join_relation)); + relation = j_relation = (struct join_relation *)MALLOC(sizeof(struct join_relation)); cmemuse++; relation->type = RELATION_TYPE_CALLING; relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new join */ @@ -280,7 +280,7 @@ JoinPBX::~JoinPBX() { struct join_relation *relation, *rtemp; - relation = c_relation; + relation = j_relation; while(relation) { rtemp = relation->next; @@ -308,7 +308,7 @@ void JoinPBX::bridge(void) int allmISDN = 1; // set until a non-mISDN relation is found #endif - relation = c_relation; + relation = j_relation; while(relation) { /* count all relations */ @@ -325,7 +325,7 @@ void JoinPBX::bridge(void) portlist = epoint->ep_portlist; if (!portlist) { - PDEBUG(DEBUG_JOIN, "join%d ignoring relation without port object.\n", c_serial); + PDEBUG(DEBUG_JOIN, "join%d ignoring relation without port object.\n", j_serial); //#warning testing: keep on hold until single audio stream available relation->channel_state = CHANNEL_STATE_HOLD; relation = relation->next; @@ -333,7 +333,7 @@ void JoinPBX::bridge(void) } if (portlist->next) { - PDEBUG(DEBUG_JOIN, "join%d ignoring relation with ep%d due to port_list.\n", c_serial, epoint->ep_serial); + PDEBUG(DEBUG_JOIN, "join%d ignoring relation with ep%d due to port_list.\n", j_serial, epoint->ep_serial); //#warning testing: keep on hold until single audio stream available relation->channel_state = CHANNEL_STATE_HOLD; relation = relation->next; @@ -342,16 +342,16 @@ void JoinPBX::bridge(void) port = find_port_id(portlist->port_id); if (!port) { - PDEBUG(DEBUG_JOIN, "join%d ignoring relation without existing port object.\n", c_serial); + PDEBUG(DEBUG_JOIN, "join%d ignoring relation without existing port object.\n", j_serial); relation = relation->next; continue; } if ((port->p_type&PORT_CLASS_MASK)!=PORT_CLASS_mISDN) { - PDEBUG(DEBUG_JOIN, "join%d ignoring relation ep%d because it's port is not mISDN.\n", c_serial, epoint->ep_serial); + PDEBUG(DEBUG_JOIN, "join%d ignoring relation ep%d because it's port is not mISDN.\n", j_serial, epoint->ep_serial); if (allmISDN) { - PDEBUG(DEBUG_JOIN, "join%d not all endpoints are mISDN.\n", c_serial); + PDEBUG(DEBUG_JOIN, "join%d not all endpoints are mISDN.\n", j_serial); allmISDN = 0; } relation = relation->next; @@ -361,9 +361,9 @@ void JoinPBX::bridge(void) relation = relation->next; } - PDEBUG(DEBUG_JOIN, "join%d members=%d %s\n", c_serial, relations, (allmISDN)?"(all are mISDN-members)":"(not all are mISDN-members)"); + PDEBUG(DEBUG_JOIN, "join%d members=%d %s\n", j_serial, relations, (allmISDN)?"(all are mISDN-members)":"(not all are mISDN-members)"); /* we notify all relations about rxdata. */ - relation = c_relation; + relation = j_relation; while(relation) { /* count connected relations */ @@ -379,17 +379,17 @@ void JoinPBX::bridge(void) && relations>1 // no conf with one member && allmISDN) // no conf if any member is not mISDN { - message = message_create(c_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL); + message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL); message->param.mISDNsignal.message = mISDNSIGNAL_CONF; - message->param.mISDNsignal.conf = c_serial<<16 | c_pid; - PDEBUG(DEBUG_JOIN, "join%d EP%d +on+ id: 0x%08x\n", c_serial, relation->epoint_id, message->param.mISDNsignal.conf); + message->param.mISDNsignal.conf = j_serial<<16 | j_pid; + PDEBUG(DEBUG_JOIN, "join%d EP%d +on+ id: 0x%08x\n", j_serial, relation->epoint_id, message->param.mISDNsignal.conf); message_put(message); } else { - message = message_create(c_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL); + message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL); message->param.mISDNsignal.message = mISDNSIGNAL_CONF; message->param.mISDNsignal.conf = 0; - PDEBUG(DEBUG_JOIN, "join%d EP%d +off+ id: 0x%08x\n", c_serial, relation->epoint_id, message->param.mISDNsignal.conf); + PDEBUG(DEBUG_JOIN, "join%d EP%d +off+ id: 0x%08x\n", j_serial, relation->epoint_id, message->param.mISDNsignal.conf); message_put(message); } @@ -399,47 +399,47 @@ void JoinPBX::bridge(void) * - any without mISDN * in this case we bridge */ - message = message_create(c_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL); + message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL); message->param.mISDNsignal.message = mISDNSIGNAL_JOINDATA; message->param.mISDNsignal.joindata = (relations==2 && !allmISDN); - PDEBUG(DEBUG_JOIN, "join%d EP%d set joindata=%d\n", c_serial, relation->epoint_id, message->param.mISDNsignal.joindata); + PDEBUG(DEBUG_JOIN, "join%d EP%d set joindata=%d\n", j_serial, relation->epoint_id, message->param.mISDNsignal.joindata); message_put(message); relation = relation->next; } /* two people just exchange their states */ - if (relations==2 && !c_partyline) + if (relations==2 && !j_partyline) { - PDEBUG(DEBUG_JOIN, "join%d 2 relations / no partyline\n", c_serial); - relation = c_relation; - relation->tx_state = notify_state_change(c_serial, relation->epoint_id, relation->tx_state, relation->next->rx_state); - relation->next->tx_state = notify_state_change(c_serial, relation->next->epoint_id, relation->next->tx_state, relation->rx_state); + PDEBUG(DEBUG_JOIN, "join%d 2 relations / no partyline\n", j_serial); + relation = j_relation; + relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, relation->next->rx_state); + relation->next->tx_state = notify_state_change(j_serial, relation->next->epoint_id, relation->next->tx_state, relation->rx_state); } else /* one member in a join, so we put her on hold */ if (relations==1 || numconnect==1) { PDEBUG(DEBUG_JOIN, "join%d 1 member or only 1 connected, put on hold\n"); - relation = c_relation; + relation = j_relation; while(relation) { if ((relation->channel_state == CHANNEL_STATE_CONNECT) && (relation->rx_state != NOTIFY_STATE_SUSPEND) && (relation->rx_state != NOTIFY_STATE_HOLD)) - relation->tx_state = notify_state_change(c_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_HOLD); + relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_HOLD); relation = relation->next; } } else /* if conference/partyline or (more than two members and more than one is connected), so we set conference state */ { PDEBUG(DEBUG_JOIN, "join%d %d members, %d connected, signal conference\n", relations, numconnect); - relation = c_relation; + relation = j_relation; while(relation) { if ((relation->channel_state == CHANNEL_STATE_CONNECT) && (relation->rx_state != NOTIFY_STATE_SUSPEND) && (relation->rx_state != NOTIFY_STATE_HOLD)) - relation->tx_state = notify_state_change(c_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_CONFERENCE); + relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_CONFERENCE); relation = relation->next; } } @@ -453,11 +453,11 @@ void JoinPBX::bridge_data(unsigned long epoint_from, struct join_relation *relat struct join_relation *relation_to; /* if we are alone */ - if (!c_relation->next) + if (!j_relation->next) return; /* if we are more than two */ - if (c_relation->next->next) + if (j_relation->next->next) return; /* skip if source endpoint has NOT audio mode CONNECT */ @@ -465,7 +465,7 @@ void JoinPBX::bridge_data(unsigned long epoint_from, struct join_relation *relat return; /* get destination relation */ - relation_to = c_relation; + relation_to = j_relation; if (relation_to == relation_from) { /* oops, we are the first, so destination is: */ @@ -480,7 +480,7 @@ void JoinPBX::bridge_data(unsigned long epoint_from, struct join_relation *relat * will be delivered to the port */ //printf("from %d, to %d\n", relation_from->epoint_id, relation_to->epoint_id); - message_forward(c_serial, relation_to->epoint_id, JOIN_TO_EPOINT, param); + message_forward(j_serial, relation_to->epoint_id, JOIN_TO_EPOINT, param); } /* release join from endpoint @@ -500,13 +500,13 @@ int JoinPBX::release(struct join_relation *relation, int location, int cause) if (relation->channel_state != CHANNEL_STATE_HOLD) { relation->channel_state = CHANNEL_STATE_HOLD; - c_updatebridge = 1; /* update bridge flag */ + j_updatebridge = 1; /* update bridge flag */ // note: if join is not released, bridge must be updated } /* detach given interface */ - reltemp = c_relation; - relationpointer = &c_relation; + reltemp = j_relation; + relationpointer = &j_relation; while(reltemp) { /* endpoint of function call */ @@ -523,7 +523,7 @@ int JoinPBX::release(struct join_relation *relation, int location, int cause) relation = reltemp = NULL; // just in case of reuse fault; /* if no more relation */ - if (!c_relation) + if (!j_relation) { PDEBUG(DEBUG_JOIN, "join is completely removed.\n"); /* there is no more endpoint related to the join */ @@ -533,15 +533,15 @@ int JoinPBX::release(struct join_relation *relation, int location, int cause) PDEBUG(DEBUG_JOIN, "join completely removed!\n"); } else /* if join is a party line */ - if (c_partyline) + if (j_partyline) { PDEBUG(DEBUG_JOIN, "join is a conference room, so we keep it alive until the last party left.\n"); } else /* if only one relation left */ - if (!c_relation->next) + if (!j_relation->next) { PDEBUG(DEBUG_JOIN, "join has one relation left, so we send it a release with the given cause %d.\n", cause); - message = message_create(c_serial, c_relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE); + message = message_create(j_serial, j_relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE); message->param.disconnectinfo.cause = cause; message->param.disconnectinfo.location = location; message_put(message); @@ -554,7 +554,7 @@ int JoinPBX::release(struct join_relation *relation, int location, int cause) join = join_first; while(join) { - if (options.deb & DEBUG_JOIN && join->c_type==JOIN_TYPE_PBX) + if (options.deb & DEBUG_JOIN && join->j_type==JOIN_TYPE_PBX) joinpbx_debug((class JoinPBX *)join, "join_release{all joins left}"); join = join->next; } @@ -576,15 +576,15 @@ int joinpbx_countrelations(unsigned long join_id) if (!join) return(0); - if (join->c_type != JOIN_TYPE_ASTERISK) + if (join->j_type != JOIN_TYPE_REMOTE) return(2); - if (join->c_type != JOIN_TYPE_PBX) + if (join->j_type != JOIN_TYPE_PBX) return(0); joinpbx = (class JoinPBX *)join; i = 0; - relation = joinpbx->c_relation; + relation = joinpbx->j_relation; while(relation) { i++; @@ -601,8 +601,8 @@ void JoinPBX::remove_relation(struct join_relation *relation) if (!relation) return; - temp = c_relation; - tempp = &c_relation; + temp = j_relation; + tempp = &j_relation; while(temp) { if (temp == relation) @@ -627,12 +627,12 @@ struct join_relation *JoinPBX::add_relation(void) { struct join_relation *relation; - if (!c_relation) + if (!j_relation) { PERROR("there is no first relation to this join\n"); return(NULL); } - relation = c_relation; + relation = j_relation; while(relation->next) relation = relation->next; @@ -676,7 +676,7 @@ void JoinPBX::message_epoint(unsigned long epoint_id, int message_type, union pa cl = join_first; while(cl) { - if (cl->c_type == JOIN_TYPE_PBX) + if (cl->j_type == JOIN_TYPE_PBX) joinpbx_debug((class JoinPBX *)cl, "Join::message_epoint{all joins before processing}"); cl = cl->next; } @@ -684,7 +684,7 @@ void JoinPBX::message_epoint(unsigned long epoint_id, int message_type, union pa } /* check relation */ - relation = c_relation; + relation = j_relation; while(relation) { if (relation->epoint_id == epoint_id) @@ -693,19 +693,19 @@ void JoinPBX::message_epoint(unsigned long epoint_id, int message_type, union pa } if (!relation) { - PDEBUG(DEBUG_JOIN, "no relation back to the endpoint found, ignoring (join=%d, endpoint=%d)\n", c_serial, epoint_id); + PDEBUG(DEBUG_JOIN, "no relation back to the endpoint found, ignoring (join=%d, endpoint=%d)\n", j_serial, epoint_id); return; } switch(message_type) { - /* process channel message */ - case MESSAGE_CHANNEL: - PDEBUG(DEBUG_JOIN, "join received channel message: %d.\n", param->channel); - if (relation->channel_state != param->channel) + /* process audio path message */ + case MESSAGE_AUDIOPATH: + PDEBUG(DEBUG_JOIN, "join received channel message: %d.\n", param->audiopath); + if (relation->channel_state != param->audiopath) { - relation->channel_state = param->channel; - c_updatebridge = 1; /* update bridge flag */ + relation->channel_state = param->audiopath; + j_updatebridge = 1; /* update bridge flag */ if (options.deb & DEBUG_JOIN) joinpbx_debug(this, "Join::message_epoint{after setting new channel state}"); } @@ -725,7 +725,7 @@ void JoinPBX::message_epoint(unsigned long epoint_id, int message_type, union pa if (new_state != relation->rx_state) { relation->rx_state = new_state; - c_updatebridge = 1; + j_updatebridge = 1; if (options.deb & DEBUG_JOIN) joinpbx_debug(this, "Join::message_epoint{after setting new rx state}"); } @@ -733,12 +733,12 @@ void JoinPBX::message_epoint(unsigned long epoint_id, int message_type, union pa default: /* send notification to all other endpoints */ - reltemp = c_relation; + reltemp = j_relation; while(reltemp) { if (reltemp->epoint_id!=epoint_id && reltemp->epoint_id) { - message = message_create(c_serial, reltemp->epoint_id, JOIN_TO_EPOINT, MESSAGE_NOTIFY); + message = message_create(j_serial, reltemp->epoint_id, JOIN_TO_EPOINT, MESSAGE_NOTIFY); memcpy(&message->param, param, sizeof(union parameter)); message_put(message); } @@ -760,7 +760,7 @@ void JoinPBX::message_epoint(unsigned long epoint_id, int message_type, union pa relation->type = RELATION_TYPE_CONNECT; /* release other relations in setup state */ release_again: - relation = c_relation; + relation = j_relation; while(relation) { if (relation->type == RELATION_TYPE_SETUP) @@ -778,8 +778,8 @@ void JoinPBX::message_epoint(unsigned long epoint_id, int message_type, union pa if (relation->type == RELATION_TYPE_SETUP) { /* collect cause and send collected cause */ - collect_cause(&c_multicause, &c_multilocation, param->disconnectinfo.cause, param->disconnectinfo.location); - release(relation, c_multilocation, c_multicause); + collect_cause(&j_multicause, &j_multilocation, param->disconnectinfo.cause, param->disconnectinfo.location); + release(relation, j_multilocation, j_multicause); } else { /* send current cause */ @@ -792,32 +792,32 @@ void JoinPBX::message_epoint(unsigned long epoint_id, int message_type, union pa if (message_type == MESSAGE_SETUP) if (param->setup.partyline) { PDEBUG(DEBUG_JOIN, "respsone with connect in partyline mode.\n"); - c_partyline = param->setup.partyline; - message = message_create(c_serial, epoint_id, JOIN_TO_EPOINT, MESSAGE_CONNECT); - message->param.setup.partyline = c_partyline; + j_partyline = param->setup.partyline; + message = message_create(j_serial, epoint_id, JOIN_TO_EPOINT, MESSAGE_CONNECT); + message->param.setup.partyline = j_partyline; message_put(message); - c_updatebridge = 1; /* update bridge flag */ + j_updatebridge = 1; /* update bridge flag */ } - if (c_partyline) + if (j_partyline) { if (message_type == MESSAGE_DISCONNECT) { PDEBUG(DEBUG_JOIN, "releasing after receiving disconnect, because join in partyline mode.\n"); - message = message_create(c_serial, epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE); + message = message_create(j_serial, epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE); message->param.disconnectinfo.cause = CAUSE_NORMAL; message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; message_put(message); return; } } - if (c_partyline) + if (j_partyline) { PDEBUG(DEBUG_JOIN, "ignoring message, because join in partyline mode.\n"); return; } /* count relations */ - num=joinpbx_countrelations(c_serial); + num=joinpbx_countrelations(j_serial); /* check number of relations */ if (num > 2) @@ -827,7 +827,7 @@ void JoinPBX::message_epoint(unsigned long epoint_id, int message_type, union pa } /* find interfaces not related to calling epoint */ - relation = c_relation; + relation = j_relation; while(relation) { if (relation->epoint_id != epoint_id) @@ -859,7 +859,7 @@ void JoinPBX::message_epoint(unsigned long epoint_id, int message_type, union pa } else { PDEBUG(DEBUG_JOIN, "sending message ep%ld -> ep%ld.\n", epoint_id, relation->epoint_id); - message = message_create(c_serial, relation->epoint_id, JOIN_TO_EPOINT, message_type); + message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, message_type); memcpy(&message->param, param, sizeof(union parameter)); message_put(message); PDEBUG(DEBUG_JOIN, "message sent.\n"); @@ -881,10 +881,10 @@ int JoinPBX::handler(void) // char *p; /* the bridge must be updated */ - if (c_updatebridge) + if (j_updatebridge) { bridge(); - c_updatebridge = 0; + j_updatebridge = 0; return(1); } @@ -945,17 +945,17 @@ int JoinPBX::out_setup(unsigned long epoint_id, int message_type, union paramete relation->tx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */ relation->rx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */ /* create a new endpoint */ - epoint = new Endpoint(0, c_serial, 0); + epoint = new Endpoint(0, j_serial, 0); if (!epoint) FATAL("No memory for Endpoint instance\n"); if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint))) FATAL("No memory for Endpoint Application instance\n"); relation->epoint_id = epoint->ep_serial; /* send setup message to new endpoint */ -//printf("JOLLY DEBUG: %d\n",join_countrelations(c_serial)); +//printf("JOLLY DEBUG: %d\n",join_countrelations(j_serial)); //i if (options.deb & DEBUG_JOIN) // joinpbx_debug(join, "Join::message_epoint"); - message = message_create(c_serial, relation->epoint_id, JOIN_TO_EPOINT, message_type); + message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, message_type); memcpy(&message->param, param, sizeof(union parameter)); if (newnumber) SCPY(message->param.setup.dialinginfo.id, newnumber); diff --git a/joinpbx.h b/joinpbx.h index dfc391a..5cdfdd5 100644 --- a/joinpbx.h +++ b/joinpbx.h @@ -58,17 +58,17 @@ class JoinPBX : public Join int handler(void); int release(struct join_relation *relation, int location, int cause); - char c_caller[32]; /* caller number */ - char c_caller_id[32]; /* caller id to signal */ - char c_dialed[1024]; /* dial string of (all) number(s) */ - char c_todial[32]; /* overlap dialing (part not signalled yet) */ - int c_multicause, c_multilocation; + char j_caller[32]; /* caller number */ + char j_caller_id[32]; /* caller id to signal */ + char j_dialed[1024]; /* dial string of (all) number(s) */ + char j_todial[32]; /* overlap dialing (part not signalled yet) */ + int j_multicause, j_multilocation; - int c_pid; /* pid of join to generate bridge id */ - int c_updatebridge; /* bridge must be updated */ - struct join_relation *c_relation; /* list of endpoints that are related to the join */ + int j_pid; /* pid of join to generate bridge id */ + int j_updatebridge; /* bridge must be updated */ + struct join_relation *j_relation; /* list of endpoints that are related to the join */ - int c_partyline; /* if set, join is conference room */ + int j_partyline; /* if set, join is conference room */ void bridge(void); void bridge_data(unsigned long epoint_from, struct join_relation *relation_from, union parameter *param); diff --git a/joinasterisk.cpp b/joinremote.cpp similarity index 60% rename from joinasterisk.cpp rename to joinremote.cpp index 0ea0633..4b5e458 100644 --- a/joinasterisk.cpp +++ b/joinremote.cpp @@ -5,7 +5,7 @@ **---------------------------------------------------------------------------** ** Copyright: Andreas Eversberg ** ** ** -** join functions for channel driver ** +** join functions for remote application ** ** ** \*****************************************************************************/ @@ -28,22 +28,29 @@ * constructor for a new join * the join will have a relation to the calling endpoint */ -JoinAsterisk::JoinAsterisk(unsigned long serial) : Join() +JoinRemote::JoinRemote(unsigned long serial, char *remote) : Join() { PDEBUG(DEBUG_JOIN, "Constructor(new join)"); + union parameter *param; - c_type = JOIN_TYPE_ASTERISK; + SCPY(j_remote, remote); + j_type = JOIN_TYPE_REMOTE; - c_epoint_id = serial; - if (c_epoint_id) - PDEBUG(DEBUG_JOIN, "New join connected to endpoint id %lu\n", c_epoint_id); + j_epoint_id = serial; + if (j_epoint_id) + PDEBUG(DEBUG_JOIN, "New remote join connected to endpoint id %lu and application %s\n", j_epoint_id, remote); + + /* send new ref to remote socket */ + memset(¶m, 0, sizeof(param)); + if (admin_message_from_join(j_remote, j_serial, MESSAGE_NEWREF, param)<0) + FATAL("No socket with remote application '%s' found, this shall not happen. because we already created one.\n", j_remote); } /* * join descructor */ -JoinAsterisk::~JoinAsterisk() +JoinRemote::~JoinRemote() { } @@ -53,22 +60,22 @@ JoinAsterisk::~JoinAsterisk() * it processes the current calling state. * returns 0 if join nothing was done */ -int JoinAsterisk::handler(void) +int JoinRemote::handler(void) { return(0); } -void JoinAsterisk::message_epoint(unsigned long epoint_id, int message_type, union parameter *param) +void JoinRemote::message_epoint(unsigned long epoint_id, int message_type, union parameter *param) { /* if endpoint has just been removed, but still a message in the que */ - if (epoint_id != c_epoint_id) + if (epoint_id != j_epoint_id) return; - /* look for asterisk's interface */ - if (admin_message_from_join(epoint_id, message_type, param)<0) + /* look for Remote's interface */ + if (admin_message_from_join(j_remote, j_serial, message_type, param)<0) { - PERROR("No socket with asterisk found, this shall not happen. Closing socket shall cause release of all asterisk joins\n"); + PERROR("No socket with remote application '%s' found, this shall not happen. Closing socket shall cause release of all joins.\n", j_remote); return; } @@ -79,22 +86,22 @@ void JoinAsterisk::message_epoint(unsigned long epoint_id, int message_type, uni } } -void JoinAsterisk::message_asterisk(unsigned long ref, int message_type, union parameter *param) +void JoinRemote::message_remote(unsigned long ref, int message_type, union parameter *param) { struct message *message; /* create relation if no relation exists */ - if (!c_epoint_id) + if (!j_epoint_id) { class Endpoint *epoint; - if (!(epoint = new Endpoint(0, c_serial, ref))) + if (!(epoint = new Endpoint(0, j_serial, ref))) FATAL("No memory for Endpoint instance\n"); if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint))) FATAL("No memory for Endpoint Application instance\n"); } - message = message_create(c_serial, c_epoint_id, JOIN_TO_EPOINT, message_type); + message = message_create(j_serial, j_epoint_id, JOIN_TO_EPOINT, message_type); memcpy(&message->param, param, sizeof(message->param)); message_put(message); diff --git a/joinasterisk.h b/joinremote.h similarity index 80% rename from joinasterisk.h rename to joinremote.h index dfd0927..d9e7e2b 100644 --- a/joinasterisk.h +++ b/joinremote.h @@ -9,16 +9,17 @@ ** ** \*****************************************************************************/ -class JoinAsterisk : public Join +class JoinRemote : public Join { public: - JoinAsterisk(unsigned long serial); - ~JoinAsterisk(); + JoinRemote(unsigned long serial, char *remote); + ~JoinRemote(); void message_epoint(unsigned long epoint_id, int message, union parameter *param); - void message_asterisk(unsigned long ref, int message_type, union parameter *param); + void message_remote(unsigned long ref, int message_type, union parameter *param); int handler(void); - unsigned long c_epoint_id; + char j_remote[32]; + unsigned long j_epoint_id; }; diff --git a/mISDN.cpp b/mISDN.cpp index 128faef..eab914a 100644 --- a/mISDN.cpp +++ b/mISDN.cpp @@ -1,6 +1,6 @@ /*****************************************************************************\ ** ** -** PBX4Linux ** +** Linux Call Router ** ** ** **---------------------------------------------------------------------------** ** Copyright: Andreas Eversberg ** @@ -25,9 +25,17 @@ extern "C" { #include } +#if 0 +#ifndef ISDN_PID_L2_B_USER #define ISDN_PID_L2_B_USER 0x420000ff +#endif +#ifndef ISDN_PID_L3_B_USER #define ISDN_PID_L3_B_USER 0x430000ff +#endif +#endif +#ifndef ISDN_PID_L4_B_USER #define ISDN_PID_L4_B_USER 0x440000ff +#endif /* used for udevice */ int entity = 0; @@ -381,15 +389,15 @@ failed: * subfunction for bchannel_event * activate request */ -static void _bchannel_activate(struct mISDNport *mISDNport, int i) +static void _bchannel_activate(struct mISDNport *mISDNport, int i, int activate) { iframe_t act; /* activate bchannel */ - chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL activate", DIRECTION_OUT); + chan_trace_header(mISDNport, mISDNport->b_port[i], activate?(char*)"BCHANNEL activate":(char*)"BCHANNEL deactivate", DIRECTION_OUT); add_trace("channel", NULL, "%d", i+1+(i>=15)); end_trace(); - act.prim = DL_ESTABLISH | REQUEST; + act.prim = (activate?DL_ESTABLISH:DL_RELEASE) | REQUEST; act.addr = mISDNport->b_addr[i] | FLG_MSG_DOWN; act.dinfo = 0; act.len = 0; @@ -441,24 +449,6 @@ static void _bchannel_configure(struct mISDNport *mISDNport, int i) /* * subfunction for bchannel_event - * deactivate - */ -static void _bchannel_deactivate(struct mISDNport *mISDNport, int i) -{ - iframe_t dact; - - chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL deactivate", DIRECTION_OUT); - add_trace("channel", NULL, "%d", i+1+(i>=15)); - end_trace(); - dact.prim = DL_RELEASE | REQUEST; - dact.addr = mISDNport->b_addr[i] | FLG_MSG_DOWN; - dact.dinfo = 0; - dact.len = 0; - mISDN_write(mISDNdevice, &dact, mISDN_HEADER_LEN+dact.len, TIMEOUT_1SEC); -} - -/* - * subfunction for bchannel_event * destroy stack */ static void _bchannel_destroy(struct mISDNport *mISDNport, int i) @@ -471,11 +461,13 @@ static void _bchannel_destroy(struct mISDNport *mISDNport, int i) add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]); end_trace(); /* remove our stack only if set */ - PDEBUG(DEBUG_BCHANNEL, "free stack (b_addr=0x%x)\n", mISDNport->b_addr[i]); - mISDN_clear_stack(mISDNdevice, mISDNport->b_stid[i]); if (mISDNport->b_addr[i]) + { + PDEBUG(DEBUG_BCHANNEL, "free stack (b_addr=0x%x)\n", mISDNport->b_addr[i]); + mISDN_clear_stack(mISDNdevice, mISDNport->b_stid[i]); mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i] | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); - mISDNport->b_addr[i] = 0; + mISDNport->b_addr[i] = 0; + } } @@ -547,7 +539,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event) /* create stack and send activation request */ if (_bchannel_create(mISDNport, i)) { - _bchannel_activate(mISDNport, i); + _bchannel_activate(mISDNport, i, 1); state = B_STATE_ACTIVATING; } break; @@ -577,7 +569,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event) } else { /* bchannel is active, but not used anymore (or has wrong stack config), so we deactivate */ - _bchannel_deactivate(mISDNport, i); + _bchannel_activate(mISDNport, i, 0); state = B_STATE_DEACTIVATING; } break; @@ -602,7 +594,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event) case B_STATE_ACTIVE: /* bchannel is active, so we deactivate */ - _bchannel_deactivate(mISDNport, i); + _bchannel_activate(mISDNport, i, 0); state = B_STATE_DEACTIVATING; break; @@ -630,7 +622,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event) /* bchannel is now deactivate, but is requied by Port class, so we reactivate */ if (_bchannel_create(mISDNport, i)) { - _bchannel_activate(mISDNport, i); + _bchannel_activate(mISDNport, i, 1); state = B_STATE_ACTIVATING; } } @@ -2300,7 +2292,7 @@ void mISDN_port_info(void) if (stinf->pid.protocol[p]) { useable = 0; - printf(" -> Layer %d protocol 0x%08x is detected, but not allowed for NT lib.\n", p, stinf->pid.protocol[p]); + printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]); } p++; } @@ -2351,7 +2343,7 @@ void mISDN_port_info(void) if (stinf->pid.protocol[p]) { useable = 0; - printf(" -> Layer %d protocol 0x%08x is detected, but not allowed for TE lib.\n", p, stinf->pid.protocol[p]); + printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]); } p++; } @@ -2359,7 +2351,7 @@ void mISDN_port_info(void) printf(" - %d B-channels\n", stinf->childcnt); if (!useable) - printf(" * Port NOT useable for PBX\n"); + printf(" * Port NOT useable for LCR\n"); printf("--------\n"); diff --git a/main.h b/main.h index 496f087..9fbf128 100644 --- a/main.h +++ b/main.h @@ -132,7 +132,7 @@ extern "C" { #include "vbox.h" #include "join.h" #include "joinpbx.h" -#include "joinasterisk.h" +#include "joinremote.h" #include "cause.h" #include "alawulaw.h" #include "tones.h" diff --git a/message.h b/message.h index cdc8163..ae1e8fd 100644 --- a/message.h +++ b/message.h @@ -274,6 +274,10 @@ struct param_crypt { unsigned char data[512+32]; /* a block of 512 byte + some overhead */ }; +struct param_hello { + char application[32]; /* name of remote application */ +}; + /* structure of message parameter */ union parameter { struct param_tone tone; /* MESSAGE_TONE */ @@ -287,7 +291,7 @@ union parameter { struct park_info parkinfo; /* MESSAGE_SUSPEND, MESSAGE_RESUME */ int state; /* MESSAGE_TIMEOUT */ int knock; /* MESSAGE_KNOCK 0=off !0=on */ - int channel; /* MESSAGE_CHANNEL see RELATION_CHANNEL_* (join.h) */ + int audiopath; /* MESSAGE_audiopath see RELATION_CHANNEL_* (join.h) */ struct param_data data; /* MESSAGE_DATA */ struct param_play play; /* MESSAGE_VBOX_PLAY */ int speed; /* MESSAGE_VBOX_PLAY_SPEED */ @@ -295,6 +299,7 @@ union parameter { struct param_mISDNsignal mISDNsignal; /* MESSAGE_mISDNSIGNAL */ struct extension ext; /* tell port about extension information */ struct param_crypt crypt; /* MESSAGE_CRYPT */ + struct param_hello hello; /* MESSAGE_HELLO */ }; enum { /* message flow */ @@ -336,7 +341,7 @@ enum { /* messages between entities */ MESSAGE_SUSPEND, /* suspend port */ MESSAGE_RESUME, /* resume port */ - MESSAGE_CHANNEL, /* set status of audio path to endpoint (to call, audio is also set) */ + MESSAGE_AUDIOPATH, /* set status of audio path to endpoint (to call, audio is also set) */ // MESSAGE_REMOTE_AUDIO, /* tell remote to set audio status */ MESSAGE_PATTERN, /* pattern information tones available */ MESSAGE_NOPATTERN, /* pattern information tones unavailable */ @@ -349,7 +354,9 @@ enum { /* messages between entities */ MESSAGE_VBOX_TONE, /* set answering VBOX tone */ MESSAGE_TONE_COUNTER, /* tone counter (for VBOX tone use) */ MESSAGE_TONE_EOF, /* tone is end of file */ - MESSAGE_HELLO, /* hello message for asterisk */ + MESSAGE_BCHANNEL, /* request/assign bchannel */ + MESSAGE_HELLO, /* hello message for remote application */ + MESSAGE_NEWREF, /* special message to create and inform ref */ }; #define MESSAGES static const char *messages_txt[] = { \ @@ -370,7 +377,7 @@ enum { /* messages between entities */ "MESSAGE_FACILITY", \ "MESSAGE_SUSPEND", \ "MESSAGE_RESUME", \ - "MESSAGE_CHANNEL", \ + "MESSAGE_AUDIOPATH", \ /* "MESSAGE_REMOTE_AUDIO",*/ \ "MESSAGE_PATTERN", \ "MESSAGE_NOPATTERN", \ @@ -381,7 +388,9 @@ enum { /* messages between entities */ "MESSAGE_VBOX_TONE", \ "MESSAGE_TONE_COUNTER", \ "MESSAGE_TONE_EOF", \ + "MESSAGE_BCHANNEL", \ "MESSAGE_HELLO", \ + "MESSAGE_NEWREF", \ }; diff --git a/route.c b/route.c index f0c7c8a..3381251 100644 --- a/route.c +++ b/route.c @@ -92,10 +92,10 @@ struct cond_defs cond_defs[] = { "busy=[,...]","Matches if any of the given extension is busy."}, { "notbusy", MATCH_IDLE, COND_TYPE_STRING, "notbusy=[,...]","Matches if any of the given extension is not busy."}, - { "asterisk", MATCH_ASTERISK, COND_TYPE_NULL, - "asterisk","Matches if asterisk is not running with LCR channel driver."}, - { "notasterisk",MATCH_NOTASTERISK,COND_TYPE_NULL, - "notasterisk","Matches if asterisk is not running with LCR channel driver."}, + { "remote", MATCH_REMOTE, COND_TYPE_STRING, + "remote=","Matches if remote application is running."}, + { "notremote", MATCH_NOTREMOTE,COND_TYPE_NULL, + "notremote=","Matches if remote application is not running."}, { NULL, 0, 0, NULL} }; @@ -229,6 +229,9 @@ struct param_defs param_defs[] = { { PARAM_STRIP, "strip", PARAM_TYPE_NULL, "strip", "Remove digits that were required to match this rule."}, + { PARAM_APPLICATION, + "application",PARAM_TYPE_STRING, + "application", "Name of remote application to make call to."}, { 0, NULL, 0, NULL, NULL} }; @@ -245,10 +248,10 @@ struct action_defs action_defs[] = { "outdial", &EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_external, &EndpointAppPBX::action_hangup_call, PARAM_CONNECT | PARAM_PREFIX | PARAM_COMPLETE | PARAM_TYPE | PARAM_CAPA | PARAM_BMODE | PARAM_INFO1 | PARAM_HLC | PARAM_EXTHLC | PARAM_PRESENT | PARAM_INTERFACES | PARAM_CALLERID | PARAM_CALLERIDTYPE | PARAM_TIMEOUT, "Same as 'extern'"}, - { ACTION_CHAN, - "asterisk", &EndpointAppPBX::action_init_chan, &EndpointAppPBX::action_dialing_chan, &EndpointAppPBX::action_hangup_call, - PARAM_CONNECT | PARAM_TIMEOUT, - "Call is routed to Asterisk via channel driver."}, + { ACTION_REMOTE, + "remote", &EndpointAppPBX::action_init_remote, &EndpointAppPBX::action_dialing_remote, &EndpointAppPBX::action_hangup_call, + PARAM_CONNECT | PARAM_APPLICATION | PARAM_TIMEOUT, + "Call is routed to Remote application, like Asterisk."}, { ACTION_VBOX_RECORD, "vbox-record",&EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_vbox_record, &EndpointAppPBX::action_hangup_call, PARAM_CONNECT | PARAM_EXTENSION | PARAM_ANNOUNCEMENT | PARAM_TIMEOUT, @@ -2208,18 +2211,18 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) istrue = 1; break; - case MATCH_ASTERISK: - case MATCH_NOTASTERISK: - admin = admin_list; + case MATCH_REMOTE: + case MATCH_NOTREMOTE: + admin = admin_first; while(admin) { - if (admin->asterisk) + if (admin->remote[0] && !strcmp(cond->string_value, admin->remote)) break; admin = admin->next; } - if (admin && cond->match==MATCH_ASTERISK) + if (admin && cond->match==MATCH_REMOTE) istrue = 1; - if (!admin && cond->match==MATCH_NOTASTERISK) + if (!admin && cond->match==MATCH_NOTREMOTE) istrue = 1; break; @@ -2425,10 +2428,10 @@ struct route_action action_internal = { 0, }; -struct route_action action_chan = { +struct route_action action_remote = { NULL, NULL, - ACTION_CHAN, + ACTION_REMOTE, 0, 0, }; diff --git a/route.h b/route.h index c83ffcc..7b5fded 100644 --- a/route.h +++ b/route.h @@ -72,8 +72,8 @@ enum { /* what to check during runtime */ MATCH_UP, MATCH_BUSY, MATCH_IDLE, - MATCH_ASTERISK, - MATCH_NOTASTERISK, + MATCH_REMOTE, + MATCH_NOTREMOTE, }; enum { /* how to parse text file during startup */ @@ -134,6 +134,7 @@ enum { /* how to parse text file during startup */ #define PARAM_TIMEOUT (1LL<<40) #define PARAM_NOPASSWORD (1LL<<41) #define PARAM_STRIP (1LL<<42) +#define PARAM_APPLICATION (1LL<<43) /* action index @@ -142,7 +143,7 @@ enum { /* how to parse text file during startup */ #define ACTION_EXTERNAL 0 #define ACTION_INTERNAL 1 #define ACTION_OUTDIAL 2 -#define ACTION_CHAN 3 +#define ACTION_REMOTE 3 #define ACTION_VBOX_RECORD 4 #define ACTION_PARTYLINE 5 #define ACTION_LOGIN 6 @@ -255,7 +256,7 @@ extern struct route_ruleset *ruleset_first; extern struct route_ruleset *ruleset_main; extern struct route_action action_external; extern struct route_action action_internal; -extern struct route_action action_chan; +extern struct route_action action_remote; extern struct route_action action_vbox; extern struct route_action action_partyline; extern struct route_action action_password; diff --git a/todo.txt b/todo.txt index 38bb842..e4eee99 100644 --- a/todo.txt +++ b/todo.txt @@ -1,3 +1,4 @@ + make asterisk call implementation display message during nothing/play @@ -28,3 +29,16 @@ facility: diversion, 3pty, ... VLAN-Kamera + +chan.cpp + +struct Channel *chan_first; + +chan->bchannel_receive + +struct ChanAsterisk *chanasterisk; + + + + + diff --git a/trace.c b/trace.c index 02a39b3..f7ff74b 100644 --- a/trace.c +++ b/trace.c @@ -307,7 +307,7 @@ void end_trace(void) } /* process admin */ - admin = admin_list; + admin = admin_first; while(admin) { if (admin->trace.detail) -- 2.13.6