X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=chan_lcr.c;h=6458de57338b545c4987155793170c316e151753;hp=47c41b6f77fd8c0aa2ecae4b8180e3e39e3ad7c4;hb=27b95197734350cc99c29929c2527f2c6d5541d6;hpb=14f76f1e81f0a4e7a63e83136d1ac958bf85c8a5 diff --git a/chan_lcr.c b/chan_lcr.c index 47c41b6..6458de5 100644 --- a/chan_lcr.c +++ b/chan_lcr.c @@ -40,15 +40,44 @@ with that reference. #include #include #include -#include "macro.h" + +#include +#include + #include "extension.h" #include "message.h" -#include "admin.h" +#include "lcrsocket.h" #include "cause.h" #include "bchannel.h" #include "chan_lcr.h" -int sock; + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int lcr_debug=1; +int mISDN_created=1; + + +int lcr_sock = -1; struct admin_list { struct admin_list *next; @@ -93,7 +122,7 @@ struct chan_call *alloc_call(void) while(*callp) callp = &((*callp)->next); - *callp = (struct chan_call *)MALLOC(sizeof(struct chan_call)); + *callp = (struct chan_call *)malloc(sizeof(struct chan_call)); return(*callp); } @@ -113,6 +142,28 @@ void free_call(struct chan_call *call) } } +unsigned short new_brige_id(void) +{ + struct chan_call *call; + unsigned short id = 1; + + /* search for lowest bridge id that is not in use and not 0 */ + while(id) + { + call = call_first; + while(call) + { + if (call->bridge_id == id) + break; + call = call->next; + } + if (!call) + break; + id++; + } + return(id); +} + /* * receive bchannel data @@ -135,7 +186,7 @@ int send_message(int message_type, unsigned long ref, union parameter *param) adminp = &admin_first; while(*adminp) adminp = &((*adminp)->next); - admin = (struct admin_list *)MALLOC(sizeof(struct admin_list)); + admin = (struct admin_list *)malloc(sizeof(struct admin_list)); *adminp = admin; admin->msg.type = message_type; @@ -164,14 +215,14 @@ int receive_message(int message_type, unsigned long ref, union parameter *param) case BCHANNEL_ASSIGN: if ((bchannel = find_bchannel_handle(param->bchannel.handle))) { - fprintf(stderr, "error: bchannel handle %x already assigned.\n", param->bchannel.handle); + fprintf(stderr, "error: bchannel handle %x already assigned.\n", (int)param->bchannel.handle); return(-1); } /* create bchannel */ bchannel = alloc_bchannel(param->bchannel.handle); if (!bchannel) { - fprintf(stderr, "error: alloc bchannel handle %x failed.\n", param->bchannel.handle); + fprintf(stderr, "error: alloc bchannel handle %x failed.\n", (int)param->bchannel.handle); return(-1); } @@ -196,6 +247,8 @@ int receive_message(int message_type, unsigned long ref, union parameter *param) { bchannel->ref = ref; call->bchannel_handle = param->bchannel.handle; +#warning hier muesen alle stati gesetzt werden falls sie vor dem b-kanal verfügbar waren + bchannel_join(bchannel, call->bridge_id); } if (bchannel_create(bchannel)) bchannel_activate(bchannel, 1); @@ -209,7 +262,8 @@ int receive_message(int message_type, unsigned long ref, union parameter *param) case BCHANNEL_REMOVE: if (!(bchannel = find_bchannel_handle(param->bchannel.handle))) { - fprintf(stderr, "error: bchannel handle %x not assigned.\n", param->bchannel.handle); + #warning alle fprintf nach ast_log + fprintf(stderr, "error: bchannel handle %x not assigned.\n", (int)param->bchannel.handle); return(-1); } /* unlink from call */ @@ -280,15 +334,57 @@ int receive_message(int message_type, unsigned long ref, union parameter *param) /* handle messages */ switch(message_type) { -#warning we must see if ref is a reply or a request, do we?? + case MESSAGE_SETUP: +#warning todo + break; + + case MESSAGE_OVERLAP: +#warning todo + break; + + case MESSAGE_PROCEEDING: +#warning todo + break; + + case MESSAGE_ALERTING: +#warning todo + break; + + case MESSAGE_CONNECT: +#warning todo + break; + + case MESSAGE_DISCONNECT: +#warning todo + break; + case MESSAGE_RELEASE: -#warning release call +#warning todo free_call(call); return(0); - case MESSAGE_SETUP: -#warning handle incoming setup, send to asterisk + case MESSAGE_INFORMATION: +#warning todo break; + + case MESSAGE_FACILITY: +#warning todo + break; + + case MESSAGE_PATTERN: +#warning todo + break; + + case MESSAGE_NOPATTERN: +#warning todo + break; + + case MESSAGE_AUDIOPATH: +#warning todo + break; + + default: +#warning unhandled } return(0); } @@ -305,6 +401,9 @@ int handle_socket(void) struct admin_message msg; struct admin_list *admin; + int sock; + + #warning SOCKET FEHLT! /* read from socket */ len = read(sock, &msg, sizeof(msg)); if (len == 0) @@ -355,7 +454,7 @@ int handle_socket(void) } /* free head */ admin_first = admin->next; - FREE(admin, 0); + free(admin); work = 1; } else @@ -371,61 +470,72 @@ int handle_socket(void) } /* - * main function + * open and close socket */ -int main(int argc, char *argv[]) +int open_socket(void) { + int ret; + int sock; char *socket_name = SOCKET_NAME; int conn; struct sockaddr_un sock_address; - int ret; unsigned long on = 1; union parameter param; - int work; /* open socket */ if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "Failed to create socket.\n"); - exit(EXIT_FAILURE); + ast_log(LOG_ERROR, "Failed to create socket.\n"); + return(sock); } /* set socket address and name */ memset(&sock_address, 0, sizeof(sock_address)); sock_address.sun_family = PF_UNIX; - UCPY(sock_address.sun_path, socket_name); + strcpy(sock_address.sun_path, socket_name); /* connect socket */ if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0) { close(sock); - fprintf(stderr, "Failed to connect to socket \"%s\".\nIs LCR running?\n", sock_address.sun_path); - exit(EXIT_FAILURE); + ast_log(LOG_ERROR, "Failed to connect to socket \"%s\". Is LCR running?\n", sock_address.sun_path); + return(conn); } /* set non-blocking io */ - if (ioctl(sock, FIONBIO, (unsigned char *)(&on)) < 0) + if ((ret = ioctl(sock, FIONBIO, (unsigned char *)(&on))) < 0) { close(sock); - fprintf(stderr, "Failed to set socket into non-blocking IO.\n"); - exit(EXIT_FAILURE); + ast_log(LOG_ERROR, "Failed to set socket into non-blocking IO.\n"); + return(ret); } /* enque hello message */ memset(¶m, 0, sizeof(param)); - SCPY(param.hello.application, "asterisk"); + strcpy(param.hello.application, "asterisk"); send_message(MESSAGE_HELLO, 0, ¶m); - /* bchannel */ - if (!bchannel_initialize()) - goto bchannel_failed; - + return(sock); +} + +void close_socket(int sock) +{ + /* close socket */ + if (socket >= 0) + close(sock); +} + + +void lcr_thread(void) +{ + int work; + while(42) { work = 0; /* handle socket */ - ret = handle_socket(); + int ret = handle_socket(); if (ret < 0) break; if (ret) @@ -439,21 +549,313 @@ int main(int argc, char *argv[]) if (!work) usleep(30000); } +} + +static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause) +{ + +} + + +/* call from asterisk (new instance) */ +static int lcr_call(struct ast_channel *ast, char *dest, int timeout) +{ + struct lcr_pvt *lcr=ast->tech_pvt; + + if (!lcr) return -1; + + char buf[128]; + char *port_str, *dad, *p; + + ast_copy_string(buf, dest, sizeof(buf)-1); + p=buf; + port_str=strsep(&p, "/"); + dad=strsep(&p, "/"); + + if (lcr_debug) + ast_verbose("Call: ext:%s dest:(%s) -> dad(%s) \n", ast->exten,dest, dad); + + + return 0; +} + +static int lcr_answer(struct ast_channel *c) +{ + struct lcr_pvt *lcr=c->tech_pvt; + return 0; +} + +static int lcr_hangup(struct ast_channel *c) +{ + struct lcr_pvt *lcr=c->tech_pvt; + c->tech_pvt=NULL; +} + + +static int lcr_write(struct ast_channel *c, struct ast_frame *f) +{ + struct lcr_pvt *lcrm= c->tech_pvt; +} + + +static struct ast_frame *lcr_read(struct ast_channel *c) +{ + struct lcr_pvt *lcr = c->tech_pvt; +} + +static int lcr_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen) +{ + int res = -1; + + switch (cond) { + case AST_CONTROL_BUSY: + case AST_CONTROL_CONGESTION: + case AST_CONTROL_RINGING: + return -1; + case -1: + return 0; + + case AST_CONTROL_VIDUPDATE: + res = -1; + break; + case AST_CONTROL_HOLD: + ast_verbose(" << Console Has Been Placed on Hold >> \n"); + //ast_moh_start(c, data, g->mohinterpret); + break; + case AST_CONTROL_UNHOLD: + ast_verbose(" << Console Has Been Retrieved from Hold >> \n"); + //ast_moh_stop(c); + break; + + default: + ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name); + return -1; + } + + return 0; +} + +static struct ast_channel_tech lcr_tech = { + .type="lcr", + .description="Channel driver for connecting to Linux-Call-Router", + .capabilities=AST_FORMAT_ALAW, + .requester=lcr_request, +// .send_digit=lcr_digit, + .call=lcr_call, +// .bridge=lcr_bridge, + .hangup=lcr_hangup, + .answer=lcr_answer, + .read=lcr_read, + .write=lcr_write, + .indicate=lcr_indicate, +// .fixup=lcr_fixup, +// .send_text=lcr_send_text, + .properties=0 +}; + +/* + * cli + */ +static int cli_show_lcr (int fd, int argc, char *argv[]) +{ +} + +static int cli_show_calls (int fd, int argc, char *argv[]) +{ +} + +static int cli_reload_routing (int fd, int argc, char *argv[]) +{ +} + +static int cli_reload_interfaces (int fd, int argc, char *argv[]) +{ +} + +static int cli_port_block (int fd, int argc, char *argv[]) +{ +} + +static int cli_port_unblock (int fd, int argc, char *argv[]) +{ +} + +static int cli_port_unload (int fd, int argc, char *argv[]) +{ +} + +static struct ast_cli_entry cli_show_lcr = +{ {"lcr", "show", "lcr", NULL}, + lcr_show_lcr, + "Shows current states of LCR core", + "Usage: lcr show lcr\n", +}; + +static struct ast_cli_entry cli_show_calls = +{ {"lcr", "show", "calls", NULL}, + lcr_show_calls, + "Shows current calls made by LCR and Asterisk", + "Usage: lcr show calls\n", +}; + +static struct ast_cli_entry cli_reload_routing = +{ {"lcr", "reload", "routing", NULL}, + lcr_reload_routing, + "Reloads routing conf of LCR, current uncomplete calls will be disconnected", + "Usage: lcr reload routing\n", +}; + +static struct ast_cli_entry cli_reload_interfaces = +{ {"lcr", "reload", "interfaces", NULL}, + lcr_reload_interfaces, + "Reloads interfaces conf of LCR", + "Usage: lcr reload interfaces\n", +}; + +static struct ast_cli_entry cli_port_block = +{ {"lcr", "port", "block", NULL}, + lcr_port_block, + "Blocks LCR port for further calls", + "Usage: lcr port block \"\"\n", +}; + +static struct ast_cli_entry cli_port_unblock = +{ {"lcr", "port", "unblock", NULL}, + lcr_port_unblock, + "Unblocks or loads LCR port, port is opened my mISDN", + "Usage: lcr port unblock \"\"\n", +}; + +static struct ast_cli_entry cli_port_unload = +{ {"lcr", "port", "unload", NULL}, + lcr_port_unload, + "Unloads LCR port, port is closes by mISDN", + "Usage: lcr port unload \"\"\n", +}; + + +/* + * module loading and destruction + */ +int load_module(void) +{ +// ast_mutex_init(&release_lock); + +// lcr_cfg_update_ptp(); + + if (!(lcr_sock = open_socket())) { + ast_log(LOG_ERROR, "Unable to connect\n"); + lcr_sock = -1; + /* continue with closed socket */ + } + + if (!bchannel_initialize()) { + ast_log(LOG_ERROR, "Unable to open mISDN device\n"); + return -1; + } + mISDN_created = 1; + + if (ast_channel_register(&lcr_tech)) { + ast_log(LOG_ERROR, "Unable to register channel class\n"); + return -1; + } + +#if 0 + ast_cli_register(&cli_show_lcr); + ast_cli_register(&cli_show_calls); + + ast_cli_register(&cli_reload_routing); + ast_cli_register(&cli_reload_interfaces); + ast_cli_register(&cli_port_block); + ast_cli_register(&cli_port_unblock); + ast_cli_register(&cli_port_unload); + + ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt", + "misdn_set_opt(::..):\n" + "Sets mISDN opts. and optargs\n" + "\n" + "The available options are:\n" + " d - Send display text on called phone, text is the optparam\n" + " n - don't detect dtmf tones on called channel\n" + " h - make digital outgoing call\n" + " c - make crypted outgoing call, param is keyindex\n" + " e - perform echo cancelation on this channel,\n" + " takes taps as arguments (32,64,128,256)\n" + " s - send Non Inband DTMF as inband\n" + " vr - rxgain control\n" + " vt - txgain control\n" + ); - bchannel_deinitialize(); - bchannel_failed: - /* close socket */ - close(sock); - /* now we say good bye */ - if (ret) - { - printf("%s\n", ret); - exit(EXIT_FAILURE); + lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE); + + chan_lcr_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n"); +======= + //lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE); +#endif + + return 0; +} + +int unload_module(void) +{ + /* First, take us out of the channel loop */ + ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n"); + + + ast_channel_unregister(&lcr_tech); + + if (mISDN_created) { + bchannel_deinitialize(); + mISDN_created = 0; } + + if (lcr_sock >= 0) { + close(lcr_sock); + lcr_sock = -1; + } + + return 0; +} + +static int reload_module(void) +{ +// reload_config(); + return 0; +} + + +ast_mutex_t usecnt_lock; +int usecnt; + +int usecount(void) +{ + int res; + ast_mutex_lock(&usecnt_lock); + res = usecnt; + ast_mutex_unlock(&usecnt_lock); + return res; } +char *desc="Channel driver for lcr"; +char *description(void) +{ + return desc; +} + +char *key(void) +{ + return ASTERISK_GPL_KEY; +} +#define AST_MODULE "chan_lcr" +AST_MODULE_INFO(ASTERISK_GPL_KEY, + AST_MODFLAG_DEFAULT, + "Channel driver for lcr", + .load = load_module, + .unload = unload_module, + .reload = reload_module, + );