Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:51 2009

## Asterisk developer's documentation

# chan_misdn.c

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (C) 2004, Christian Richter
    00005  *
    00006  * Christian Richter <crich@beronet.com>
    00007  *
    00008  * See http://www.asterisk.org for more information about
    00009  * the Asterisk project. Please do not directly contact
    00010  * any of the maintainers of this project for assistance;
    00011  * the project provides a web site, mailing lists and IRC
    00012  * channels for your use.
    00013  *
    00014  * This program is free software, distributed under the terms of
    00015  * the GNU General Public License Version 2. See the LICENSE file
    00016  * at the top of the source tree.
    00017  *
    00018  */
    00019
    00020 /*!
    00021  * \file
    00022  *
    00023  * \brief the chan_misdn channel driver for Asterisk
    00024  * \author Christian Richter <crich@beronet.com>
    00025  *
    00026  * \ingroup channel_drivers
    00027  */
    00028
    00029 #include <stdio.h>
    00030 #include <pthread.h>
    00031 #include <string.h>
    00032 #include <sys/socket.h>
    00033 #include <sys/time.h>
    00034 #include <errno.h>
    00035 #include <unistd.h>
    00036 #include <stdlib.h>
    00037 #include <arpa/inet.h>
    00038 #include <fcntl.h>
    00039 #include <sys/ioctl.h>
    00040 #include <signal.h>
    00041 #include <sys/file.h>
    00042 #include <semaphore.h>
    00043
    00044 #include <asterisk/channel.h>
    00045 #include <asterisk/config.h>
    00046 #include <asterisk/logger.h>
    00047 #include <asterisk/module.h>
    00048 #include <asterisk/pbx.h>
    00049 #include <asterisk/options.h>
    00050 #include <asterisk/io.h>
    00051 #include <asterisk/frame.h>
    00052 #include <asterisk/translate.h>
    00053 #include <asterisk/cli.h>
    00054 #include <asterisk/musiconhold.h>
    00055 #include <asterisk/dsp.h>
    00056 #include <asterisk/translate.h>
    00057 #include <asterisk/config.h>
    00058 #include <asterisk/file.h>
    00059 #include <asterisk/callerid.h>
    00060 #include <asterisk/indications.h>
    00061 #include <asterisk/app.h>
    00062 #include <asterisk/features.h>
    00063 #include <asterisk/sched.h>
    00064
    00065 #include <chan_misdn_config.h>
    00066 #include <isdn_lib.h>
    00067
    00068 char global_tracefile[BUFFERSIZE+1];
    00069
    00070 static int g_config_initialized=0;
    00071
    00072 struct misdn_jb{
    00073    int size;
    00074    int upper_threshold;
    00075    char *samples, *ok;
    00076    int wp,rp;
    00077    int state_empty;
    00078    int state_full;
    00079    int state_buffer;
    00080    int bytes_wrote;
    00081    ast_mutex_t mutexjb;
    00082 };
    00083
    00084
    00085
    00086 /* allocates the jb-structure and initialise the elements*/
    00087 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
    00088
    00089 /* frees the data and destroys the given jitterbuffer struct */
    00090 void misdn_jb_destroy(struct misdn_jb *jb);
    00091
    00092 /* fills the jitterbuffer with len data returns < 0 if there was an
    00093 error (bufferoverun). */
    00094 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
    00095
    00096 /* gets len bytes out of the jitterbuffer if available, else only the
    00097 available data is returned and the return value indicates the number
    00098 of data. */
    00099 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
    00100
    00101
    00102
    00103
    00104 /* BEGIN: chan_misdn.h */
    00105
    00106 ast_mutex_t release_lock;
    00107
    00108
    00109 enum misdn_chan_state {
    00110    MISDN_NOTHING=0,  /*!< at beginning */
    00111    MISDN_WAITING4DIGS, /*!<  when waiting for infos */
    00112    MISDN_EXTCANTMATCH, /*!<  when asterisk couldnt match our ext */
    00113    MISDN_INCOMING_SETUP, /*!<  for incoming setups*/
    00114    MISDN_DIALING, /*!<  when pbx_start */
    00115    MISDN_PROGRESS, /*!<  we got a progress */
    00116    MISDN_PROCEEDING, /*!<  we got a progress */
    00117    MISDN_CALLING, /*!<  when misdn_call is called */
    00118    MISDN_CALLING_ACKNOWLEDGE, /*!<  when we get SETUP_ACK */
    00119    MISDN_ALERTING, /*!<  when Alerting */
    00120    MISDN_BUSY, /*!<  when BUSY */
    00121    MISDN_CONNECTED, /*!<  when connected */
    00122    MISDN_PRECONNECTED, /*!<  when connected */
    00123    MISDN_DISCONNECTED, /*!<  when connected */
    00124    MISDN_RELEASED, /*!<  when connected */
    00125    MISDN_BRIDGED, /*!<  when bridged */
    00126    MISDN_CLEANING, /*!< when hangup from * but we were connected before */
    00127    MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
    00128    MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */
    00129    /* misdn_hangup */
    00130    MISDN_HOLDED, /*!< if this chan is holded */
    00131    MISDN_HOLD_DISCONNECT, /*!< if this chan is holded */
    00132
    00133 };
    00134
    00135 #define ORG_AST 1
    00136 #define ORG_MISDN 2
    00137
    00138 struct hold_info {
    00139    int port;
    00140    int channel;
    00141 };
    00142
    00143 struct chan_list {
    00144
    00145    ast_mutex_t lock;
    00146
    00147    char allowed_bearers[BUFFERSIZE+1];
    00148
    00149    enum misdn_chan_state state;
    00150    int need_queue_hangup;
    00151    int need_hangup;
    00152    int need_busy;
    00153
    00154    int noautorespond_on_setup;
    00155
    00156    int orginator;
    00157
    00158    int norxtone;
    00159    int notxtone;
    00160
    00161    int toggle_ec;
    00162
    00163    int incoming_early_audio;
    00164
    00165    int ignore_dtmf;
    00166
    00167    int pipe[2];
    00168    char ast_rd_buf[4096];
    00169    struct ast_frame frame;
    00170
    00171    int faxdetect;
    00172    int faxhandled;
    00173
    00174    int ast_dsp;
    00175
    00176    int jb_len;
    00177    int jb_upper_threshold;
    00178    struct misdn_jb *jb;
    00179
    00180    struct ast_dsp *dsp;
    00181    struct ast_trans_pvt *trans;
    00182
    00183    struct ast_channel * ast;
    00184
    00185    int dummy;
    00186
    00187    struct misdn_bchannel *bc;
    00188
    00189    struct hold_info hold_info;
    00190
    00191    unsigned int l3id;
    00192    int addr;
    00193
    00194    char context[BUFFERSIZE];
    00195
    00196    int zero_read_cnt;
    00197    int dropped_frame_cnt;
    00198
    00199    int far_alerting;
    00200
    00201    int nttimeout;
    00202
    00203    int other_pid;
    00204    struct chan_list *other_ch;
    00205
    00206    const struct tone_zone_sound *ts;
    00207
    00208    int overlap_dial;
    00209    int overlap_dial_task;
    00210    ast_mutex_t overlap_tv_lock;
    00211    struct timeval overlap_tv;
    00212
    00213    struct chan_list *peer;
    00214    struct chan_list *next;
    00215    struct chan_list *prev;
    00216    struct chan_list *first;
    00217 };
    00218
    00219
    00220
    00221 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
    00222 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
    00223
    00224 struct robin_list {
    00225    char *group;
    00226    int port;
    00227    int channel;
    00228    struct robin_list *next;
    00229    struct robin_list *prev;
    00230 };
    00231 static struct robin_list *robin = NULL;
    00232
    00233
    00234
    00235 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
    00236
    00237
    00238
    00239 static inline void free_robin_list_r (struct robin_list *r)
    00240 {
    00241         if (r) {
    00242                 if (r->next) free_robin_list_r(r->next);
    00243                 if (r->group) free(r->group);
    00244                 free(r);
    00245         }
    00246 }
    00247
    00248 static void free_robin_list ( void )
    00249 {
    00250    free_robin_list_r(robin);
    00251    robin = NULL;
    00252 }
    00253
    00254 static struct robin_list* get_robin_position (char *group)
    00255 {
    00256    struct robin_list *iter = robin;
    00257    for (; iter; iter = iter->next) {
    00258       if (!strcasecmp(iter->group, group))
    00259          return iter;
    00260    }
    00261    struct robin_list *new = (struct robin_list *)calloc(1, sizeof(struct robin_list));
    00262    new->group = strndup(group, strlen(group));
    00263    new->channel = 1;
    00264    if (robin) {
    00265       new->next = robin;
    00266       robin->prev = new;
    00267    }
    00268    robin = new;
    00269    return robin;
    00270 }
    00271
    00272
    00273 /* the main schedule context for stuff like l1 watcher, overlap dial, ... */
    00274 static struct sched_context *misdn_tasks = NULL;
    00275 static pthread_t misdn_tasks_thread;
    00276
    00277 static void chan_misdn_log(int level, int port, char *tmpl, ...);
    00278
    00279 static struct ast_channel *misdn_new(struct chan_list *cl, int state,  char *exten, char *callerid, int format, int port, int c);
    00280 static void send_digit_to_chan(struct chan_list *cl, char digit );
    00281
    00282 static void hangup_chan(struct chan_list *ch);
    00283 static int pbx_start_chan(struct chan_list *ch);
    00284
    00285 #define AST_CID_P(ast) ast->cid.cid_num
    00286 #define AST_BRIDGED_P(ast) ast_bridged_channel(ast)
    00287 #define AST_LOAD_CFG ast_config_load
    00288 #define AST_DESTROY_CFG ast_config_destroy
    00289
    00290 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
    00291 #define MISDN_ASTERISK_PVT(ast) 1
    00292
    00293 #include <asterisk/strings.h>
    00294
    00295 /* #define MISDN_DEBUG 1 */
    00296
    00297 static char *desc = "Channel driver for mISDN Support (Bri/Pri)";
    00298 static const char misdn_type[] = "mISDN";
    00299
    00300 static int tracing = 0 ;
    00301
    00302 static int usecnt=0;
    00303
    00304 /* Only alaw and mulaw is allowed for now */
    00305 static int prefformat =  AST_FORMAT_ALAW ; /*  AST_FORMAT_SLINEAR ;  AST_FORMAT_ULAW | */
    00306
    00307 static ast_mutex_t usecnt_lock;
    00308
    00309 static int *misdn_debug;
    00310 static int *misdn_debug_only;
    00311 static int max_ports;
    00312
    00313 struct chan_list dummy_cl;
    00314
    00315 struct chan_list *cl_te=NULL;
    00316 ast_mutex_t cl_te_lock;
    00317
    00318 static enum event_response_e
    00319 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
    00320
    00321 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch);
    00322
    00323 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
    00324 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
    00325 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
    00326 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid);
    00327
    00328
    00329
    00330 static int dialtone_indicate(struct chan_list *cl);
    00331 static int hanguptone_indicate(struct chan_list *cl);
    00332 static int stop_indicate(struct chan_list *cl);
    00333
    00334 static int start_bc_tones(struct chan_list *cl);
    00335 static int stop_bc_tones(struct chan_list *cl);
    00336 static void release_chan(struct misdn_bchannel *bc);
    00337
    00338 static int misdn_check_l2l1(struct ast_channel *chan, void *data);
    00339 static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
    00340 static int misdn_facility_exec(struct ast_channel *chan, void *data);
    00341
    00342 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
    00343
    00344 #ifdef MISDN_1_2
    00345 static int update_pipeline_config(struct misdn_bchannel *bc);
    00346 #else
    00347 static int update_ec_config(struct misdn_bchannel *bc);
    00348 #endif
    00349
    00350 /*************** Helpers *****************/
    00351
    00352 static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
    00353 {
    00354    struct chan_list *tmp;
    00355
    00356    for (tmp=cl_te; tmp; tmp = tmp->next) {
    00357       if ( tmp->ast == ast ) return tmp;
    00358    }
    00359
    00360    return NULL;
    00361 }
    00362
    00363 static struct chan_list * get_chan_by_ast_name(char *name)
    00364 {
    00365    struct chan_list *tmp;
    00366
    00367    for (tmp=cl_te; tmp; tmp = tmp->next) {
    00368       if ( tmp->ast  && strcmp(tmp->ast->name,name) == 0) return tmp;
    00369    }
    00370
    00371    return NULL;
    00372 }
    00373
    00374
    00375
    00376 struct allowed_bearers {
    00377    int cap;
    00378    int val;
    00379    char *name;
    00380 };
    00381
    00382 struct allowed_bearers allowed_bearers_array[]={
    00383    {INFO_CAPABILITY_SPEECH,1,"speech"},
    00384    {INFO_CAPABILITY_AUDIO_3_1K,2,"3_1khz"},
    00385    {INFO_CAPABILITY_DIGITAL_UNRESTRICTED,4,"digital_unrestricted"},
    00386    {INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restriced"},
    00387    {INFO_CAPABILITY_VIDEO,16,"video"}
    00388 };
    00389
    00390 static char *bearer2str(int cap) {
    00391    static char *bearers[]={
    00392       "Speech",
    00393       "Audio 3.1k",
    00394       "Unres Digital",
    00395       "Res Digital",
    00396       "Video",
    00397       "Unknown Bearer"
    00398    };
    00399
    00400    switch (cap) {
    00401    case INFO_CAPABILITY_SPEECH:
    00402       return bearers[0];
    00403       break;
    00404    case INFO_CAPABILITY_AUDIO_3_1K:
    00405       return bearers[1];
    00406       break;
    00407    case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
    00408       return bearers[2];
    00409       break;
    00410    case INFO_CAPABILITY_DIGITAL_RESTRICTED:
    00411       return bearers[3];
    00412       break;
    00413    case INFO_CAPABILITY_VIDEO:
    00414       return bearers[4];
    00415       break;
    00416    default:
    00417       return bearers[5];
    00418       break;
    00419    }
    00420 }
    00421
    00422
    00423 static void print_facility( struct misdn_bchannel *bc)
    00424 {
    00425    switch (bc->fac_type) {
    00426    case FACILITY_CALLDEFLECT:
    00427       chan_misdn_log(2,bc->port," --> calldeflect: %s\n",
    00428                 bc->fac.calldeflect_nr);
    00429       break;
    00430    case FACILITY_CENTREX:
    00431       chan_misdn_log(2,bc->port," --> centrex: %s\n",
    00432                 bc->fac.cnip);
    00433       break;
    00434    default:
    00435       chan_misdn_log(2,bc->port," --> unknown\n");
    00436
    00437    }
    00438 }
    00439
    00440 static void print_bearer(struct misdn_bchannel *bc)
    00441 {
    00442
    00443    chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
    00444
    00445    switch(bc->law) {
    00446    case INFO_CODEC_ALAW:
    00447       chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
    00448       break;
    00449    case INFO_CODEC_ULAW:
    00450       chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
    00451       break;
    00452    }
    00453 }
    00454 /*************** Helpers END *************/
    00455
    00456 static void sighandler(int sig)
    00457 {}
    00458
    00459 static void* misdn_tasks_thread_func (void *data)
    00460 {
    00461    int wait;
    00462    struct sigaction sa;
    00463
    00464    sa.sa_handler = sighandler;
    00465    sa.sa_flags = SA_NODEFER;
    00466    sigemptyset(&sa.sa_mask);
    00467    sigaddset(&sa.sa_mask, SIGUSR1);
    00468    sigaction(SIGUSR1, &sa, NULL);
    00469
    00470    sem_post((sem_t *)data);
    00471
    00472    while (1) {
    00473       wait = ast_sched_wait(misdn_tasks);
    00474       if (wait < 0)
    00475          wait = 8000;
    00476       if (poll(NULL, 0, wait) < 0)
    00477          chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
    00478       ast_sched_runq(misdn_tasks);
    00479    }
    00480    return NULL;
    00481 }
    00482
    00483 static void misdn_tasks_init (void)
    00484 {
    00485    sem_t blocker;
    00486    int i = 5;
    00487
    00488    if (sem_init(&blocker, 0, 0)) {
    00489       perror("chan_misdn: Failed to initialize semaphore!");
    00490       exit(1);
    00491    }
    00492
    00493    chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
    00494
    00495    misdn_tasks = sched_context_create();
    00496    pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
    00497
    00498    while (sem_wait(&blocker) && --i);
    00499    sem_destroy(&blocker);
    00500 }
    00501
    00502 static void misdn_tasks_destroy (void)
    00503 {
    00504    if (misdn_tasks) {
    00505       chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
    00506       if ( pthread_cancel(misdn_tasks_thread) == 0 ) {
    00507          cb_log(4, 0, "Joining misdn_tasks thread\n");
    00508          pthread_join(misdn_tasks_thread, NULL);
    00509       }
    00510       sched_context_destroy(misdn_tasks);
    00511    }
    00512 }
    00513
    00514 static inline void misdn_tasks_wakeup (void)
    00515 {
    00516    pthread_kill(misdn_tasks_thread, SIGUSR1);
    00517 }
    00518
    00519 static inline int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, void *data, int variable)
    00520 {
    00521    int task_id;
    00522
    00523    if (!misdn_tasks) {
    00524       misdn_tasks_init();
    00525    }
    00526    task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
    00527    misdn_tasks_wakeup();
    00528
    00529    return task_id;
    00530 }
    00531
    00532 #if 0
    00533 static int misdn_tasks_add (int timeout, ast_sched_cb callback, void *data)
    00534 {
    00535    return _misdn_tasks_add_variable(timeout, callback, data, 0);
    00536 }
    00537 #endif
    00538
    00539 static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, void *data)
    00540 {
    00541    return _misdn_tasks_add_variable(timeout, callback, data, 1);
    00542 }
    00543
    00544 static void misdn_tasks_remove (int task_id)
    00545 {
    00546    ast_sched_del(misdn_tasks, task_id);
    00547 }
    00548
    00549 static int misdn_overlap_dial_task (void *data)
    00550 {
    00551    struct timeval tv_end, tv_now;
    00552    int diff;
    00553    struct chan_list *ch = (struct chan_list *)data;
    00554
    00555    chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
    00556
    00557    if (ch->state != MISDN_WAITING4DIGS) {
    00558       ch->overlap_dial_task = -1;
    00559       return 0;
    00560    }
    00561
    00562    ast_mutex_lock(&ch->overlap_tv_lock);
    00563    tv_end = ch->overlap_tv;
    00564    ast_mutex_unlock(&ch->overlap_tv_lock);
    00565
    00566    tv_end.tv_sec += ch->overlap_dial;
    00567    tv_now = ast_tvnow();
    00568
    00569    diff = ast_tvdiff_ms(tv_end, tv_now);
    00570
    00571    if (diff <= 100) {
    00572       /* if we are 100ms near the timeout, we are satisfied.. */
    00573       stop_indicate(ch);
    00574       if (ast_exists_extension(ch->ast, ch->context, ch->bc->dad, 1, ch->bc->oad)) {
    00575          ch->state=MISDN_DIALING;
    00576          if (pbx_start_chan(ch) < 0) {
    00577             chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
    00578             goto misdn_overlap_dial_task_disconnect;
    00579          }
    00580       } else {
    00581 misdn_overlap_dial_task_disconnect:
    00582          hanguptone_indicate(ch);
    00583          if (ch->bc->nt)
    00584             misdn_lib_send_event(ch->bc, EVENT_RELEASE_COMPLETE );
    00585          else
    00586             misdn_lib_send_event(ch->bc, EVENT_RELEASE);
    00587       }
    00588       ch->overlap_dial_task = -1;
    00589       return 0;
    00590    } else
    00591       return diff;
    00592 }
    00593
    00594 static void send_digit_to_chan(struct chan_list *cl, char digit )
    00595 {
    00596    static const char* dtmf_tones[] = {
    00597       "!941+1336/100,!0/100", /* 0 */
    00598       "!697+1209/100,!0/100", /* 1 */
    00599       "!697+1336/100,!0/100", /* 2 */
    00600       "!697+1477/100,!0/100", /* 3 */
    00601       "!770+1209/100,!0/100", /* 4 */
    00602       "!770+1336/100,!0/100", /* 5 */
    00603       "!770+1477/100,!0/100", /* 6 */
    00604       "!852+1209/100,!0/100", /* 7 */
    00605       "!852+1336/100,!0/100", /* 8 */
    00606       "!852+1477/100,!0/100", /* 9 */
    00607       "!697+1633/100,!0/100", /* A */
    00608       "!770+1633/100,!0/100", /* B */
    00609       "!852+1633/100,!0/100", /* C */
    00610       "!941+1633/100,!0/100", /* D */
    00611       "!941+1209/100,!0/100", /* * */
    00612       "!941+1477/100,!0/100" };  /* # */
    00613    struct ast_channel *chan=cl->ast;
    00614
    00615    if (digit >= '0' && digit <='9')
    00616       ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
    00617    else if (digit >= 'A' && digit <= 'D')
    00618       ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
    00619    else if (digit == '*')
    00620       ast_playtones_start(chan,0,dtmf_tones[14], 0);
    00621    else if (digit == '#')
    00622       ast_playtones_start(chan,0,dtmf_tones[15], 0);
    00623    else {
    00624       /* not handled */
    00625       ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
    00626
    00627
    00628    }
    00629 }
    00630 /*** CLI HANDLING ***/
    00631 static int misdn_set_debug(int fd, int argc, char *argv[])
    00632 {
    00633    if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
    00634       return RESULT_SHOWUSAGE;
    00635
    00636    int level = atoi(argv[3]);
    00637
    00638    switch (argc) {
    00639       case 4:
    00640       case 5: {
    00641                int only = 0;
    00642                if (argc == 5) {
    00643                   if (strncasecmp(argv[4], "only", strlen(argv[4])))
    00644                      return RESULT_SHOWUSAGE;
    00645                   else
    00646                      only = 1;
    00647                }
    00648                int i;
    00649                for (i=0; i<=max_ports; i++) {
    00650                   misdn_debug[i] = level;
    00651                   misdn_debug_only[i] = only;
    00652                }
    00653                ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
    00654             }
    00655             break;
    00656       case 6:
    00657       case 7: {
    00658                if (strncasecmp(argv[4], "port", strlen(argv[4])))
    00659                   return RESULT_SHOWUSAGE;
    00660                int port = atoi(argv[5]);
    00661                if (port <= 0 || port > max_ports) {
    00662                   switch (max_ports) {
    00663                      case 0:
    00664                         ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
    00665                         break;
    00666                      case 1:
    00667                         ast_cli(fd, "port number not valid! only port 1 is availble.\n");
    00668                         break;
    00669                      default:
    00670                         ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
    00671                      }
    00672                      return 0;
    00673                }
    00674                if (argc == 7) {
    00675                   if (strncasecmp(argv[6], "only", strlen(argv[6])))
    00676                      return RESULT_SHOWUSAGE;
    00677                   else
    00678                      misdn_debug_only[port] = 1;
    00679                } else
    00680                   misdn_debug_only[port] = 0;
    00681                misdn_debug[port] = level;
    00682                ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
    00683             }
    00684    }
    00685    return 0;
    00686 }
    00687
    00688 static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
    00689 {
    00690    if (argc != 5) return RESULT_SHOWUSAGE;
    00691
    00692    return 0;
    00693 }
    00694
    00695
    00696 static int misdn_port_block(int fd, int argc, char *argv[])
    00697 {
    00698    int port;
    00699
    00700    if (argc != 4)
    00701       return RESULT_SHOWUSAGE;
    00702
    00703    port = atoi(argv[3]);
    00704
    00705    misdn_lib_port_block(port);
    00706
    00707    return 0;
    00708 }
    00709
    00710 static int misdn_port_unblock(int fd, int argc, char *argv[])
    00711 {
    00712    int port;
    00713
    00714    if (argc != 4)
    00715       return RESULT_SHOWUSAGE;
    00716
    00717    port = atoi(argv[3]);
    00718
    00719    misdn_lib_port_unblock(port);
    00720
    00721    return 0;
    00722 }
    00723
    00724
    00725 static int misdn_restart_port (int fd, int argc, char *argv[])
    00726 {
    00727    int port;
    00728
    00729    if (argc != 4)
    00730       return RESULT_SHOWUSAGE;
    00731
    00732    port = atoi(argv[3]);
    00733
    00734    misdn_lib_port_restart(port);
    00735
    00736    return 0;
    00737 }
    00738
    00739 static int misdn_restart_pid (int fd, int argc, char *argv[])
    00740 {
    00741    int pid;
    00742
    00743    if (argc != 4)
    00744       return RESULT_SHOWUSAGE;
    00745
    00746    pid = atoi(argv[3]);
    00747
    00748    misdn_lib_pid_restart(pid);
    00749
    00750    return 0;
    00751 }
    00752
    00753 static int misdn_port_up (int fd, int argc, char *argv[])
    00754 {
    00755    int port;
    00756
    00757    if (argc != 4)
    00758       return RESULT_SHOWUSAGE;
    00759
    00760    port = atoi(argv[3]);
    00761
    00762    misdn_lib_get_port_up(port);
    00763
    00764    return 0;
    00765 }
    00766
    00767 static int misdn_port_down (int fd, int argc, char *argv[])
    00768 {
    00769    int port;
    00770
    00771    if (argc != 4)
    00772       return RESULT_SHOWUSAGE;
    00773
    00774    port = atoi(argv[3]);
    00775
    00776    misdn_lib_get_port_down(port);
    00777
    00778    return 0;
    00779 }
    00780
    00781
    00782 static int misdn_show_config (int fd, int argc, char *argv[])
    00783 {
    00784    char buffer[BUFFERSIZE];
    00785    enum misdn_cfg_elements elem;
    00786    int linebreak;
    00787
    00788    int onlyport = -1;
    00789    if (argc >= 4) {
    00790       if (!sscanf(argv[3], "%30d", &onlyport) || onlyport < 0) {
    00791          ast_cli(fd, "Unknown option: %s\n", argv[3]);
    00792          return RESULT_SHOWUSAGE;
    00793       }
    00794    }
    00795
    00796    if (argc == 3 || onlyport == 0) {
    00797       ast_cli(fd,"Misdn General-Config: \n");
    00798       ast_cli(fd," -> Version: chan_misdn-" CHAN_MISDN_VERSION "\n");
    00799       for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
    00800          misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE);
    00801          ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
    00802       }
    00803       ast_cli(fd, "\n");
    00804    }
    00805
    00806    if (onlyport < 0) {
    00807       int port = misdn_cfg_get_next_port(0);
    00808       for (; port > 0; port = misdn_cfg_get_next_port(port)) {
    00809          ast_cli(fd, "\n[PORT %d]\n", port);
    00810          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
    00811             misdn_cfg_get_config_string( port, elem, buffer, BUFFERSIZE);
    00812             ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
    00813          }
    00814          ast_cli(fd, "\n");
    00815       }
    00816    }
    00817
    00818    if (onlyport > 0) {
    00819       if (misdn_cfg_is_port_valid(onlyport)) {
    00820          ast_cli(fd, "[PORT %d]\n", onlyport);
    00821          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
    00822             misdn_cfg_get_config_string( onlyport, elem, buffer, BUFFERSIZE);
    00823             ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
    00824          }
    00825          ast_cli(fd, "\n");
    00826       } else {
    00827          ast_cli(fd, "Port %d is not active!\n", onlyport);
    00828       }
    00829    }
    00830    return 0;
    00831 }
    00832
    00833 struct state_struct {
    00834    enum misdn_chan_state state;
    00835    char txt[255] ;
    00836 } ;
    00837
    00838 static struct state_struct state_array[] = {
    00839    {MISDN_NOTHING,"NOTHING"}, /* at beginning */
    00840    {MISDN_WAITING4DIGS,"WAITING4DIGS"}, /*  when waiting for infos */
    00841    {MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /*  when asterisk couldnt match our ext */
    00842    {MISDN_INCOMING_SETUP,"INCOMING SETUP"}, /*  when pbx_start */
    00843    {MISDN_DIALING,"DIALING"}, /*  when pbx_start */
    00844    {MISDN_PROGRESS,"PROGRESS"}, /*  when pbx_start */
    00845    {MISDN_PROCEEDING,"PROCEEDING"}, /*  when pbx_start */
    00846    {MISDN_CALLING,"CALLING"}, /*  when misdn_call is called */
    00847    {MISDN_CALLING_ACKNOWLEDGE,"CALLING_ACKNOWLEDGE"}, /*  when misdn_call is called */
    00848    {MISDN_ALERTING,"ALERTING"}, /*  when Alerting */
    00849    {MISDN_BUSY,"BUSY"}, /*  when BUSY */
    00850    {MISDN_CONNECTED,"CONNECTED"}, /*  when connected */
    00851    {MISDN_PRECONNECTED,"PRECONNECTED"}, /*  when connected */
    00852    {MISDN_DISCONNECTED,"DISCONNECTED"}, /*  when connected */
    00853    {MISDN_RELEASED,"RELEASED"}, /*  when connected */
    00854    {MISDN_BRIDGED,"BRIDGED"}, /*  when bridged */
    00855    {MISDN_CLEANING,"CLEANING"}, /* when hangup from * but we were connected before */
    00856    {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
    00857    {MISDN_HOLDED,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
    00858    {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
    00859    {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of */
    00860    /* misdn_hangup */
    00861 };
    00862
    00863 static char *misdn_get_ch_state(struct chan_list *p)
    00864 {
    00865    int i;
    00866    static char state[8];
    00867
    00868    if( !p) return NULL;
    00869
    00870    for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
    00871       if ( state_array[i].state == p->state) return state_array[i].txt;
    00872    }
    00873
    00874    sprintf(state,"%d",p->state) ;
    00875
    00876    return state;
    00877 }
    00878
    00879
    00880
    00881 static void reload_config(void)
    00882 {
    00883    int i, cfg_debug;
    00884
    00885    if (!g_config_initialized) {
    00886       ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
    00887       return ;
    00888    }
    00889
    00890    free_robin_list();
    00891    misdn_cfg_reload();
    00892    misdn_cfg_update_ptp();
    00893    misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
    00894    misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
    00895
    00896    for (i = 0;  i <= max_ports; i++) {
    00897       misdn_debug[i] = cfg_debug;
    00898       misdn_debug_only[i] = 0;
    00899    }
    00900 }
    00901
    00902 static int misdn_reload (int fd, int argc, char *argv[])
    00903 {
    00904    ast_cli(fd, "Reloading mISDN Config\n");
    00905    reload_config();
    00906    return 0;
    00907 }
    00908
    00909 static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel* bc)
    00910 {
    00911    struct ast_channel *ast=help->ast;
    00912    ast_cli(fd,
    00913       "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
    00914
    00915       bc->pid, bc->port, bc->channel,
    00916       bc->nt?"NT":"TE",
    00917       help->orginator == ORG_AST?"*":"I",
    00918       ast?ast->exten:NULL,
    00919       ast?AST_CID_P(ast):NULL,
    00920       bc->rad,
    00921       ast?ast->context:NULL,
    00922       misdn_get_ch_state(help)
    00923       );
    00924    if (misdn_debug[bc->port] > 0)
    00925       ast_cli(fd,
    00926          "  --> astname: %s\n"
    00927          "  --> ch_l3id: %x\n"
    00928          "  --> ch_addr: %x\n"
    00929          "  --> bc_addr: %x\n"
    00930          "  --> bc_l3id: %x\n"
    00931          "  --> display: %s\n"
    00932          "  --> activated: %d\n"
    00933          "  --> state: %s\n"
    00934          "  --> capability: %s\n"
    00935 #ifdef MISDN_1_2
    00936          "  --> pipeline: %s\n"
    00937 #else
    00938          "  --> echo_cancel: %d\n"
    00939 #endif
    00940          "  --> notone : rx %d tx:%d\n"
    00941          "  --> bc_hold: %d\n",
    00942          help->ast->name,
    00943          help->l3id,
    00944          help->addr,
    00945          bc->addr,
    00946          bc?bc->l3_id:-1,
    00947          bc->display,
    00948
    00949          bc->active,
    00950          bc_state2str(bc->bc_state),
    00951          bearer2str(bc->capability),
    00952 #ifdef MISDN_1_2
    00953          bc->pipeline,
    00954 #else
    00955          bc->ec_enable,
    00956 #endif
    00957
    00958          help->norxtone,help->notxtone,
    00959          bc->holded
    00960          );
    00961
    00962 }
    00963
    00964 static int misdn_show_cls (int fd, int argc, char *argv[])
    00965 {
    00966    struct chan_list *help=cl_te;
    00967
    00968    ast_cli(fd,"Chan List: %p\n",cl_te);
    00969
    00970    for (;help; help=help->next) {
    00971       struct misdn_bchannel *bc=help->bc;
    00972       struct ast_channel *ast=help->ast;
    00973       if (misdn_debug[0] > 2) ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
    00974       if (bc) {
    00975          print_bc_info(fd, help, bc);
    00976       } else {
    00977          if (help->state == MISDN_HOLDED) {
    00978             ast_cli(fd, "ITS A HOLDED BC:\n");
    00979             ast_cli(fd, " --> l3_id: %x\n"
    00980                   " --> dad:%s oad:%s\n"
    00981
    00982                   ,help->l3id
    00983                   ,ast->exten
    00984                   ,AST_CID_P(ast)
    00985                   );
    00986          } else {
    00987             ast_cli(fd,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, AST_CID_P(ast));
    00988          }
    00989       }
    00990    }
    00991
    00992    misdn_dump_chanlist();
    00993    return 0;
    00994 }
    00995
    00996 static int misdn_show_cl (int fd, int argc, char *argv[])
    00997 {
    00998    struct chan_list *help=cl_te;
    00999
    01000    if (argc != 4)
    01001       return RESULT_SHOWUSAGE;
    01002
    01003    for (;help; help=help->next) {
    01004       struct misdn_bchannel *bc=help->bc;
    01005       struct ast_channel *ast=help->ast;
    01006
    01007       if (bc && ast) {
    01008          if (!strcasecmp(ast->name,argv[3])) {
    01009             print_bc_info(fd, help, bc);
    01010             break;
    01011          }
    01012       }
    01013    }
    01014
    01015
    01016    return 0;
    01017 }
    01018
    01019 ast_mutex_t lock;
    01020 int MAXTICS=8;
    01021
    01022 static int misdn_set_tics (int fd, int argc, char *argv[])
    01023 {
    01024    if (argc != 4)
    01025       return RESULT_SHOWUSAGE;
    01026
    01027    MAXTICS=atoi(argv[3]);
    01028
    01029    return 0;
    01030 }
    01031
    01032 static int misdn_show_stacks (int fd, int argc, char *argv[])
    01033 {
    01034    int port;
    01035
    01036    ast_cli(fd, "BEGIN STACK_LIST:\n");
    01037
    01038    for (port=misdn_cfg_get_next_port(0); port > 0;
    01039         port=misdn_cfg_get_next_port(port)) {
    01040       char buf[128];
    01041       get_show_stack_details(port,buf);
    01042       ast_cli(fd,"  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
    01043    }
    01044
    01045
    01046    return 0;
    01047
    01048 }
    01049
    01050 static int misdn_show_port (int fd, int argc, char *argv[])
    01051 {
    01052    int port;
    01053
    01054    if (argc != 4)
    01055       return RESULT_SHOWUSAGE;
    01056
    01057    port = atoi(argv[3]);
    01058
    01059    ast_cli(fd, "BEGIN STACK_LIST:\n");
    01060
    01061    char buf[128];
    01062    get_show_stack_details(port,buf);
    01063    ast_cli(fd,"  %s  Debug:%d%s\n",buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
    01064
    01065
    01066    return 0;
    01067 }
    01068
    01069 static int misdn_send_cd (int fd, int argc, char *argv[])
    01070 {
    01071    char *channame;
    01072    char *nr;
    01073
    01074    if (argc != 5)
    01075       return RESULT_SHOWUSAGE;
    01076
    01077    channame = argv[3];
    01078    nr = argv[4];
    01079
    01080    ast_cli(fd, "Sending Calldeflection (%s) to %s\n",nr, channame);
    01081
    01082    {
    01083       struct chan_list *tmp=get_chan_by_ast_name(channame);
    01084
    01085       if (!tmp) {
    01086          ast_cli(fd, "Sending CD with nr %s to %s failed Channel does not exist\n",nr, channame);
    01087          return 0;
    01088       } else {
    01089
    01090          misdn_lib_send_facility(tmp->bc, FACILITY_CALLDEFLECT, nr);
    01091       }
    01092    }
    01093
    01094    return 0;
    01095 }
    01096
    01097 static int misdn_send_restart(int fd, int argc, char *argv[])
    01098 {
    01099    int port;
    01100    int channel;
    01101
    01102    if ( (argc < 4) ||  (argc >  5) )
    01103       return RESULT_SHOWUSAGE;
    01104
    01105    port = atoi(argv[3]);
    01106
    01107    if (argc==5) {
    01108       channel = atoi(argv[4]);
    01109       misdn_lib_send_restart(port, channel);
    01110    } else
    01111       misdn_lib_send_restart(port, -1 );
    01112
    01113    return 0;
    01114 }
    01115
    01116
    01117
    01118 static int misdn_send_digit (int fd, int argc, char *argv[])
    01119 {
    01120    char *channame;
    01121    char *msg;
    01122
    01123    if (argc != 5)
    01124       return RESULT_SHOWUSAGE;
    01125
    01126    channame = argv[3];
    01127    msg = argv[4];
    01128
    01129    ast_cli(fd, "Sending %s to %s\n",msg, channame);
    01130
    01131    {
    01132       struct chan_list *tmp=get_chan_by_ast_name(channame);
    01133
    01134       if (!tmp) {
    01135          ast_cli(fd, "Sending %s to %s failed Channel does not exist\n",msg, channame);
    01136          return 0;
    01137       } else {
    01138 #if 1
    01139          int i;
    01140          int msglen = strlen(msg);
    01141          for (i=0; i<msglen; i++) {
    01142             ast_cli(fd, "Sending: %c\n",msg[i]);
    01143             send_digit_to_chan(tmp, msg[i]);
    01144             /* res = ast_safe_sleep(tmp->ast, 250); */
    01145             usleep(250000);
    01146             /* res = ast_waitfor(tmp->ast,100); */
    01147          }
    01148 #else
    01149          int res;
    01150          res = ast_dtmf_stream(tmp->ast,NULL,msg,250);
    01151 #endif
    01152       }
    01153    }
    01154
    01155    return 0;
    01156 }
    01157
    01158 static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
    01159 {
    01160    char *channame;
    01161
    01162    if (argc != 4)
    01163       return RESULT_SHOWUSAGE;
    01164
    01165    channame = argv[3];
    01166
    01167    ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
    01168
    01169    {
    01170       struct chan_list *tmp=get_chan_by_ast_name(channame);
    01171
    01172       if (!tmp) {
    01173          ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
    01174          return 0;
    01175       } else {
    01176
    01177          tmp->toggle_ec=tmp->toggle_ec?0:1;
    01178
    01179          if (tmp->toggle_ec) {
    01180 #ifdef MISDN_1_2
    01181             update_pipeline_config(tmp->bc);
    01182 #else
    01183             update_ec_config(tmp->bc);
    01184 #endif
    01185             manager_ec_enable(tmp->bc);
    01186          } else {
    01187             manager_ec_disable(tmp->bc);
    01188          }
    01189       }
    01190    }
    01191
    01192    return 0;
    01193 }
    01194
    01195 static int misdn_send_display (int fd, int argc, char *argv[])
    01196 {
    01197    char *channame;
    01198    char *msg;
    01199
    01200    if (argc != 5)
    01201       return RESULT_SHOWUSAGE;
    01202
    01203    channame = argv[3];
    01204    msg = argv[4];
    01205
    01206    ast_cli(fd, "Sending %s to %s\n",msg, channame);
    01207    {
    01208       struct chan_list *tmp;
    01209       tmp=get_chan_by_ast_name(channame);
    01210
    01211       if (tmp && tmp->bc) {
    01212          ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
    01213          misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
    01214       } else {
    01215          ast_cli(fd,"No such channel %s\n",channame);
    01216          return RESULT_FAILURE;
    01217       }
    01218    }
    01219
    01220    return RESULT_SUCCESS ;
    01221 }
    01222
    01223 static char *complete_ch_helper(char *line, char *word, int pos, int state, int rpos)
    01224 {
    01225    struct ast_channel *c;
    01226    int which=0;
    01227    char *ret;
    01228    if (pos != rpos)
    01229       return NULL;
    01230    c = ast_channel_walk_locked(NULL);
    01231    while(c) {
    01232       if (!strncasecmp(word, c->name, strlen(word))) {
    01233          if (++which > state)
    01234             break;
    01235       }
    01236       ast_mutex_unlock(&c->lock);
    01237       c = ast_channel_walk_locked(c);
    01238    }
    01239    if (c) {
    01240       ret = strdup(c->name);
    01241       ast_mutex_unlock(&c->lock);
    01242    } else
    01243       ret = NULL;
    01244    return ret;
    01245 }
    01246
    01247 static char *complete_ch(char *line, char *word, int pos, int state)
    01248 {
    01249    return complete_ch_helper(line, word, pos, state, 3);
    01250 }
    01251
    01252 static char *complete_debug_port (char *line, char *word, int pos, int state)
    01253 {
    01254    if (state)
    01255       return NULL;
    01256
    01257    switch (pos) {
    01258    case 4: if (*word == 'p')
    01259             return strdup("port");
    01260          else if (*word == 'o')
    01261             return strdup("only");
    01262          break;
    01263    case 6: if (*word == 'o')
    01264             return strdup("only");
    01265          break;
    01266    }
    01267    return NULL;
    01268 }
    01269
    01270 static struct ast_cli_entry cli_send_cd =
    01271 { {"misdn","send","calldeflect", NULL},
    01272   misdn_send_cd,
    01273   "Sends CallDeflection to mISDN Channel",
    01274   "Usage: misdn send calldeflect <channel> \"<nr>\" \n",
    01275   complete_ch
    01276 };
    01277
    01278 static struct ast_cli_entry cli_send_restart=
    01279 { {"misdn","send","restart", NULL},
    01280   misdn_send_restart,
    01281   "Sends a restart for every bchannel on the given port",
    01282   "Usage: misdn send restart <port>\n"
    01283 };
    01284
    01285
    01286 static struct ast_cli_entry cli_send_digit =
    01287 { {"misdn","send","digit", NULL},
    01288   misdn_send_digit,
    01289   "Sends DTMF Digit to mISDN Channel",
    01290   "Usage: misdn send digit <channel> \"<msg>\" \n"
    01291   "       Send <digit> to <channel> as DTMF Tone\n"
    01292   "       when channel is a mISDN channel\n",
    01293   complete_ch
    01294 };
    01295
    01296 static struct ast_cli_entry cli_toggle_echocancel =
    01297 { {"misdn","toggle","echocancel", NULL},
    01298   misdn_toggle_echocancel,
    01299   "Toggles EchoCancel on mISDN Channel",
    01300   "Usage: misdn toggle echocancel <channel>\n",
    01301   complete_ch
    01302 };
    01303
    01304 static struct ast_cli_entry cli_send_display =
    01305 { {"misdn","send","display", NULL},
    01306   misdn_send_display,
    01307   "Sends Text to mISDN Channel",
    01308   "Usage: misdn send display <channel> \"<msg>\" \n"
    01309   "       Send <msg> to <channel> as Display Message\n"
    01310   "       when channel is a mISDN channel\n",
    01311   complete_ch
    01312 };
    01313
    01314 static struct ast_cli_entry cli_show_config =
    01315 { {"misdn","show","config", NULL},
    01316   misdn_show_config,
    01317   "Shows internal mISDN config, read from cfg-file",
    01318   "Usage: misdn show config [port | 0]\n       use 0 to only print the general config.\n"
    01319 };
    01320
    01321 static struct ast_cli_entry cli_reload =
    01322 { {"misdn","reload", NULL},
    01323   misdn_reload,
    01324   "Reloads internal mISDN config, read from cfg-file",
    01325   "Usage: misdn reload\n"
    01326 };
    01327
    01328 static struct ast_cli_entry cli_set_tics =
    01329 { {"misdn","set","tics", NULL},
    01330   misdn_set_tics,
    01331   "",
    01332   "\n"
    01333 };
    01334
    01335 static struct ast_cli_entry cli_show_cls =
    01336 { {"misdn","show","channels", NULL},
    01337   misdn_show_cls,
    01338   "Shows internal mISDN chan_list",
    01339   "Usage: misdn show channels\n"
    01340 };
    01341
    01342 static struct ast_cli_entry cli_show_cl =
    01343 { {"misdn","show","channel", NULL},
    01344   misdn_show_cl,
    01345   "Shows internal mISDN chan_list",
    01346   "Usage: misdn show channels\n",
    01347   complete_ch
    01348 };
    01349
    01350 static struct ast_cli_entry cli_port_block=
    01351 { {"misdn","port","block", NULL},
    01352   misdn_port_block,
    01353   "Blocks the given port",
    01354   "Usage: misdn port block\n"
    01355 };
    01356
    01357 static struct ast_cli_entry cli_port_unblock=
    01358 { {"misdn","port","unblock", NULL},
    01359   misdn_port_unblock,
    01360   "Unblocks the given port",
    01361   "Usage: misdn port unblock\n"
    01362 };
    01363
    01364
    01365 static struct ast_cli_entry cli_restart_port =
    01366 { {"misdn","restart","port", NULL},
    01367   misdn_restart_port,
    01368   "Restarts the given port",
    01369   "Usage: misdn restart port\n"
    01370 };
    01371
    01372 static struct ast_cli_entry cli_restart_pid =
    01373 { {"misdn","restart","pid", NULL},
    01374   misdn_restart_pid,
    01375   "Restarts the given pid",
    01376   "Usage: misdn restart pid\n"
    01377 };
    01378
    01379 static struct ast_cli_entry cli_port_up =
    01380 { {"misdn","port","up", NULL},
    01381   misdn_port_up,
    01382   "Tries to establish L1 on the given port",
    01383   "Usage: misdn port up <port>\n"
    01384 };
    01385
    01386 static struct ast_cli_entry cli_port_down =
    01387 { {"misdn","port","down", NULL},
    01388   misdn_port_down,
    01389   "Tries to deacivate the L1 on the given port",
    01390   "Usage: misdn port down <port>\n"
    01391 };
    01392
    01393
    01394
    01395 static struct ast_cli_entry cli_show_stacks =
    01396 { {"misdn","show","stacks", NULL},
    01397   misdn_show_stacks,
    01398   "Shows internal mISDN stack_list",
    01399   "Usage: misdn show stacks\n"
    01400 };
    01401
    01402 static struct ast_cli_entry cli_show_port =
    01403 { {"misdn","show","port", NULL},
    01404   misdn_show_port,
    01405   "Shows detailed information for given port",
    01406   "Usage: misdn show port <port>\n"
    01407 };
    01408
    01409 static struct ast_cli_entry cli_set_debug =
    01410 { {"misdn","set","debug", NULL},
    01411   misdn_set_debug,
    01412   "Sets Debuglevel of chan_misdn",
    01413   "Usage: misdn set debug <level> [only] | [port <port> [only]]\n",
    01414   complete_debug_port
    01415 };
    01416
    01417 static struct ast_cli_entry cli_set_crypt_debug =
    01418 { {"misdn","set","crypt","debug", NULL},
    01419   misdn_set_crypt_debug,
    01420   "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}",
    01421   "Usage: misdn set crypt debug <level>\n"
    01422 };
    01423 /*** CLI END ***/
    01424
    01425
    01426 static int update_config (struct chan_list *ch, int orig)
    01427 {
    01428    if (!ch) {
    01429       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
    01430       return -1;
    01431    }
    01432
    01433    struct ast_channel *ast=ch->ast;
    01434    struct misdn_bchannel *bc=ch->bc;
    01435    if (! ast || ! bc ) {
    01436       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
    01437       return -1;
    01438    }
    01439
    01440    int port=bc->port;
    01441
    01442    chan_misdn_log(7,port,"update_config: Getting Config\n");
    01443
    01444    int hdlc=0;
    01445    misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
    01446
    01447    if (hdlc) {
    01448       switch (bc->capability) {
    01449       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
    01450       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
    01451          chan_misdn_log(1,bc->port," --> CONF HDLC\n");
    01452          bc->hdlc=1;
    01453          break;
    01454       }
    01455
    01456    }
    01457
    01458
    01459    int pres, screen;
    01460
    01461    misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
    01462    misdn_cfg_get( port, MISDN_CFG_SCREEN, &screen, sizeof(int));
    01463    chan_misdn_log(2,port," --> pres: %d screen: %d\n",pres, screen);
    01464
    01465    if ( (pres + screen) < 0 ) {
    01466
    01467       chan_misdn_log(2,port," --> pres: %x\n", ast->cid.cid_pres);
    01468
    01469       switch (ast->cid.cid_pres & 0x60){
    01470
    01471       case AST_PRES_RESTRICTED:
    01472          bc->pres=1;
    01473          chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
    01474          break;
    01475
    01476
    01477       case AST_PRES_UNAVAILABLE:
    01478          bc->pres=2;
    01479          chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
    01480          break;
    01481
    01482       default:
    01483          bc->pres=0;
    01484          chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
    01485       }
    01486
    01487       switch (ast->cid.cid_pres & 0x3){
    01488
    01489       case AST_PRES_USER_NUMBER_UNSCREENED:
    01490          bc->screen=0;
    01491          chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
    01492          break;
    01493
    01494       case AST_PRES_USER_NUMBER_PASSED_SCREEN:
    01495          bc->screen=1;
    01496          chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
    01497          break;
    01498       case AST_PRES_USER_NUMBER_FAILED_SCREEN:
    01499          bc->screen=2;
    01500          chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
    01501          break;
    01502
    01503       case AST_PRES_NETWORK_NUMBER:
    01504          bc->screen=3;
    01505          chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
    01506          break;
    01507
    01508       default:
    01509          bc->screen=0;
    01510          chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
    01511       }
    01512
    01513
    01514    } else {
    01515       bc->screen=screen;
    01516       bc->pres=pres;
    01517    }
    01518
    01519    return 0;
    01520
    01521 }
    01522
    01523
    01524
    01525
    01526 void config_jitterbuffer(struct chan_list *ch)
    01527 {
    01528    struct misdn_bchannel *bc=ch->bc;
    01529    int len=ch->jb_len, threshold=ch->jb_upper_threshold;
    01530
    01531    chan_misdn_log(5,bc->port, "config_jb: Called\n");
    01532
    01533    if ( ! len ) {
    01534       chan_misdn_log(1,bc->port, "config_jb: Deactivating Jitterbuffer\n");
    01535       bc->nojitter=1;
    01536    } else {
    01537
    01538       if (len <=100 || len > 8000) {
    01539          chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
    01540          len=1000;
    01541       }
    01542
    01543       if ( threshold > len ) {
    01544          chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
    01545       }
    01546
    01547       if ( ch->jb) {
    01548          cb_log(0,bc->port,"config_jb: We've got a Jitterbuffer Already on this port.\n");
    01549          misdn_jb_destroy(ch->jb);
    01550          ch->jb=NULL;
    01551       }
    01552
    01553       ch->jb=misdn_jb_init(len, threshold);
    01554
    01555       if (!ch->jb )
    01556          bc->nojitter=1;
    01557    }
    01558 }
    01559
    01560
    01561 void debug_numplan(int port, int numplan, char *type)
    01562 {
    01563    switch (numplan) {
    01564    case NUMPLAN_INTERNATIONAL:
    01565       chan_misdn_log(2, port, " --> %s: International\n",type);
    01566       break;
    01567    case NUMPLAN_NATIONAL:
    01568       chan_misdn_log(2, port, " --> %s: National\n",type);
    01569       break;
    01570    case NUMPLAN_SUBSCRIBER:
    01571       chan_misdn_log(2, port, " --> %s: Subscriber\n",type);
    01572       break;
    01573    case NUMPLAN_UNKNOWN:
    01574       chan_misdn_log(2, port, " --> %s: Unknown\n",type);
    01575       break;
    01576       /* Maybe we should cut off the prefix if present ? */
    01577    default:
    01578       chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
    01579       break;
    01580    }
    01581 }
    01582
    01583 #ifdef MISDN_1_2
    01584 static int update_pipeline_config(struct misdn_bchannel *bc)
    01585 {
    01586    int ec;
    01587
    01588    misdn_cfg_get(bc->port, MISDN_CFG_PIPELINE, bc->pipeline, sizeof(bc->pipeline));
    01589
    01590    if (*bc->pipeline)
    01591       return 0;
    01592
    01593    misdn_cfg_get(bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
    01594    if (ec == 1)
    01595       snprintf(bc->pipeline, sizeof(bc->pipeline) - 1, "mg2ec");
    01596    else if (ec > 1)
    01597       snprintf(bc->pipeline, sizeof(bc->pipeline) - 1, "mg2ec(deftaps=%d)", ec);
    01598
    01599    return 0;
    01600 }
    01601 #else
    01602 static int update_ec_config(struct misdn_bchannel *bc)
    01603 {
    01604    int ec;
    01605    int port=bc->port;
    01606
    01607    misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
    01608
    01609    if (ec == 1 ) {
    01610       bc->ec_enable=1;
    01611    } else if ( ec > 1 ) {
    01612       bc->ec_enable=1;
    01613       bc->ec_deftaps=ec;
    01614    }
    01615
    01616    return 0;
    01617 }
    01618 #endif
    01619
    01620 static int read_config(struct chan_list *ch, int orig) {
    01621
    01622    if (!ch) {
    01623       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
    01624       return -1;
    01625    }
    01626
    01627    struct ast_channel *ast=ch->ast;
    01628    struct misdn_bchannel *bc=ch->bc;
    01629    if (! ast || ! bc ) {
    01630       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
    01631       return -1;
    01632    }
    01633
    01634    int port=bc->port;
    01635
    01636    chan_misdn_log(5,port,"read_config: Getting Config\n");
    01637
    01638    char lang[BUFFERSIZE+1];
    01639
    01640    misdn_cfg_get( port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE);
    01641    ast_copy_string(ast->language, lang, sizeof(ast->language));
    01642
    01643    char musicclass[BUFFERSIZE+1];
    01644
    01645    misdn_cfg_get( port, MISDN_CFG_MUSICCLASS, musicclass, BUFFERSIZE);
    01646    ast_copy_string(ast->musicclass, musicclass, sizeof(ast->musicclass));
    01647
    01648    misdn_cfg_get( port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(int));
    01649    misdn_cfg_get( port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(int));
    01650
    01651    misdn_cfg_get( port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(int));
    01652
    01653    misdn_cfg_get( port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(int));
    01654
    01655    misdn_cfg_get( port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(int));
    01656    misdn_cfg_get( port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(int));
    01657
    01658    misdn_cfg_get( port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(int));
    01659
    01660    misdn_cfg_get( port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int));
    01661
    01662    misdn_cfg_get( port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE);
    01663
    01664
    01665    int hdlc=0;
    01666    misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
    01667
    01668    if (hdlc) {
    01669       switch (bc->capability) {
    01670       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
    01671       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
    01672          chan_misdn_log(1,bc->port," --> CONF HDLC\n");
    01673          bc->hdlc=1;
    01674          break;
    01675       }
    01676
    01677    }
    01678    /*Initialize new Jitterbuffer*/
    01679    {
    01680       misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(int));
    01681       misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(int));
    01682
    01683       config_jitterbuffer(ch);
    01684    }
    01685
    01686    misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
    01687
    01688    ast_copy_string (ast->context,ch->context,sizeof(ast->context));
    01689
    01690 #ifdef MISDN_1_2
    01691    update_pipeline_config(bc);
    01692 #else
    01693    update_ec_config(bc);
    01694 #endif
    01695
    01696    {
    01697       int eb3;
    01698
    01699       misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
    01700       bc->early_bconnect=eb3;
    01701    }
    01702
    01703    port=bc->port;
    01704
    01705    {
    01706       char buf[256];
    01707       ast_group_t pg,cg;
    01708
    01709       misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
    01710       misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
    01711
    01712       chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
    01713       ast->pickupgroup=pg;
    01714       ast->callgroup=cg;
    01715    }
    01716
    01717    if ( orig  == ORG_AST) {
    01718       misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(int));
    01719
    01720       {
    01721          char callerid[BUFFERSIZE+1];
    01722          misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
    01723          if ( ! ast_strlen_zero(callerid) ) {
    01724             chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
    01725             {
    01726                int l = sizeof(bc->oad);
    01727                strncpy(bc->oad,callerid, l);
    01728                bc->oad[l-1] = 0;
    01729             }
    01730
    01731          }
    01732
    01733
    01734          misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(int));
    01735          misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(int));
    01736          misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
    01737          debug_numplan(port, bc->dnumplan,"TON");
    01738          debug_numplan(port, bc->onumplan,"LTON");
    01739          debug_numplan(port, bc->cpnnumplan,"CTON");
    01740       }
    01741
    01742       ch->overlap_dial = 0;
    01743    } else { /** ORIGINATOR MISDN **/
    01744
    01745       misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
    01746       debug_numplan(port, bc->cpnnumplan,"CTON");
    01747
    01748       char prefix[BUFFERSIZE+1]="";
    01749       switch( bc->onumplan ) {
    01750       case NUMPLAN_INTERNATIONAL:
    01751          misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
    01752          break;
    01753
    01754       case NUMPLAN_NATIONAL:
    01755          misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
    01756          break;
    01757       default:
    01758          break;
    01759       }
    01760
    01761       {
    01762          int l = strlen(prefix) + strlen(bc->oad);
    01763          char tmp[l+1];
    01764          strcpy(tmp,prefix);
    01765          strcat(tmp,bc->oad);
    01766          strcpy(bc->oad,tmp);
    01767       }
    01768
    01769       if (!ast_strlen_zero(bc->dad)) {
    01770          ast_copy_string(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
    01771       }
    01772
    01773       if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
    01774          ast_copy_string(bc->dad,bc->keypad, sizeof(bc->dad));
    01775       }
    01776
    01777       prefix[0] = 0;
    01778
    01779       switch( bc->dnumplan ) {
    01780       case NUMPLAN_INTERNATIONAL:
    01781          misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
    01782          break;
    01783       case NUMPLAN_NATIONAL:
    01784          misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
    01785          break;
    01786       default:
    01787          break;
    01788       }
    01789
    01790       {
    01791          int l = strlen(prefix) + strlen(bc->dad);
    01792          char tmp[l+1];
    01793          strcpy(tmp,prefix);
    01794          strcat(tmp,bc->dad);
    01795          strcpy(bc->dad,tmp);
    01796       }
    01797
    01798       if ( strcmp(bc->dad,ast->exten)) {
    01799          ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
    01800       }
    01801
    01802       ast_set_callerid(ast, bc->oad, NULL, bc->oad);
    01803
    01804       if ( !ast_strlen_zero(bc->rad) )
    01805          ast->cid.cid_rdnis=strdup(bc->rad);
    01806
    01807       misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
    01808       ast_mutex_init(&ch->overlap_tv_lock);
    01809    } /* ORIG MISDN END */
    01810
    01811    ch->overlap_dial_task = -1;
    01812
    01813    return 0;
    01814 }
    01815
    01816
    01817 /*****************************/
    01818 /*** AST Indications Start ***/
    01819 /*****************************/
    01820
    01821 static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
    01822 {
    01823    int port=0;
    01824    int r;
    01825    struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
    01826    struct misdn_bchannel *newbc;
    01827    char *opts=NULL, *ext;
    01828    char dest_cp[256];
    01829
    01830    {
    01831       strncpy(dest_cp,dest,sizeof(dest_cp)-1);
    01832       dest_cp[sizeof(dest_cp)]=0;
    01833
    01834       ext=dest_cp;
    01835       strsep(&ext,"/");
    01836       if (ext) {
    01837          opts=ext;
    01838          strsep(&opts,"/");
    01839       }  else {
    01840          ast_log(LOG_WARNING, "Malformed dialstring\n");
    01841          return -1;
    01842       }
    01843    }
    01844
    01845    if (!ast) {
    01846       ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
    01847       return -1;
    01848    }
    01849
    01850    if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest  ) {
    01851       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
    01852       ast->hangupcause=41;
    01853       ast_setstate(ast, AST_STATE_DOWN);
    01854       return -1;
    01855    }
    01856
    01857    if (!ch) {
    01858       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
    01859       ast->hangupcause=41;
    01860       ast_setstate(ast, AST_STATE_DOWN);
    01861       return -1;
    01862    }
    01863
    01864    newbc=ch->bc;
    01865
    01866    if (!newbc) {
    01867       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
    01868       ast->hangupcause=41;
    01869       ast_setstate(ast, AST_STATE_DOWN);
    01870       return -1;
    01871    }
    01872
    01873    port=newbc->port;
    01874
    01875
    01876    chan_misdn_log(1, port, "* CALL: %s\n",dest);
    01877
    01878    chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
    01879
    01880    chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
    01881    if (ast->exten) {
    01882       int l = sizeof(newbc->dad);
    01883       strncpy(ast->exten,ext,sizeof(ast->exten));
    01884
    01885       strncpy(newbc->dad,ext,l);
    01886
    01887       newbc->dad[l-1] = 0;
    01888    }
    01889    newbc->rad[0]=0;
    01890    chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",AST_CID_P(ast));
    01891    if (ast_strlen_zero(newbc->oad) && AST_CID_P(ast) ) {
    01892
    01893       if (AST_CID_P(ast)) {
    01894          int l = sizeof(newbc->oad);
    01895          strncpy(newbc->oad,AST_CID_P(ast), l);
    01896          newbc->oad[l-1] = 0;
    01897       }
    01898    }
    01899
    01900    {
    01901       struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
    01902       if (!ch) { ast_verbose("No chan_list in misdn_call\n"); return -1;}
    01903
    01904       newbc->capability=ast->transfercapability;
    01905       pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
    01906       if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
    01907          chan_misdn_log(2, port, " --> * Call with flag Digital\n");
    01908       }
    01909
    01910
    01911       /* update screening and presentation */
    01912       update_config(ch,ORG_AST);
    01913
    01914       /* fill in some ies from channel vary*/
    01915       import_ch(ast, newbc, ch);
    01916
    01917       /* Finally The Options Override Everything */
    01918       if (opts)
    01919          misdn_set_opt_exec(ast,opts);
    01920       else
    01921          chan_misdn_log(2,port,"NO OPTS GIVEN\n");
    01922
    01923       /*check for bridging*/
    01924       int bridging;
    01925       misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
    01926       if (bridging && ch->other_ch) {
    01927 #ifdef MISDN_1_2
    01928          chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
    01929          *ch->bc->pipeline=0;
    01930          *ch->other_ch->bc->pipeline=0;
    01931 #else
    01932          chan_misdn_log(1, port, "Disabling EC on both Sides\n");
    01933          ch->bc->ec_enable=0;
    01934          ch->other_ch->bc->ec_enable=0;
    01935 #endif
    01936       }
    01937
    01938       r=misdn_lib_send_event( newbc, EVENT_SETUP );
    01939
    01940       /** we should have l3id after sending setup **/
    01941       ch->l3id=newbc->l3_id;
    01942    }
    01943
    01944    if ( r == -ENOCHAN  ) {
    01945       chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
    01946       chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1);
    01947       ast->hangupcause=34;
    01948       ast_setstate(ast, AST_STATE_DOWN);
    01949       return -1;
    01950    }
    01951
    01952    chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
    01953
    01954    ast_setstate(ast, AST_STATE_DIALING);
    01955    ast->hangupcause=16;
    01956
    01957    if (newbc->nt) stop_bc_tones(ch);
    01958
    01959    ch->state=MISDN_CALLING;
    01960
    01961    return 0;
    01962 }
    01963
    01964
    01965 static int misdn_answer(struct ast_channel *ast)
    01966 {
    01967    struct chan_list *p;
    01968
    01969
    01970    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
    01971
    01972    chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
    01973
    01974    if (!p) {
    01975       ast_log(LOG_WARNING, " --> Channel not connected ??\n");
    01976       ast_queue_hangup(ast);
    01977    }
    01978
    01979    if (!p->bc) {
    01980       chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
    01981
    01982       ast_queue_hangup(ast);
    01983    }
    01984
    01985    {
    01986       const char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
    01987
    01988       if (tmp_key ) {
    01989          chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
    01990          {
    01991             int l = sizeof(p->bc->crypt_key);
    01992             strncpy(p->bc->crypt_key,tmp_key, l);
    01993             p->bc->crypt_key[l-1] = 0;
    01994          }
    01995       } else {
    01996          chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
    01997       }
    01998
    01999    }
    02000
    02001    {
    02002       const char *nodsp=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
    02003       if (nodsp) {
    02004          chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
    02005          p->bc->nodsp=1;
    02006          p->bc->hdlc=0;
    02007          p->bc->nojitter=1;
    02008       }
    02009    }
    02010
    02011    p->state = MISDN_CONNECTED;
    02012    stop_indicate(p);
    02013
    02014    if ( ast_strlen_zero(p->bc->cad) ) {
    02015       chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
    02016       ast_copy_string(p->bc->cad,p->bc->dad,sizeof(p->bc->cad));
    02017    }
    02018
    02019    misdn_lib_send_event( p->bc, EVENT_CONNECT);
    02020    start_bc_tones(p);
    02021
    02022    return 0;
    02023 }
    02024
    02025 static int misdn_digit(struct ast_channel *ast, char digit )
    02026 {
    02027    struct chan_list *p;
    02028
    02029    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1;
    02030
    02031    struct misdn_bchannel *bc=p->bc;
    02032    chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
    02033
    02034    if (!bc) {
    02035       ast_log(LOG_WARNING, " --> !! Got Digit Event withut having bchannel Object\n");
    02036       return -1;
    02037    }
    02038
    02039    switch (p->state ) {
    02040       case MISDN_CALLING:
    02041       {
    02042
    02043          char buf[8];
    02044          buf[0]=digit;
    02045          buf[1]=0;
    02046
    02047          int l = sizeof(bc->infos_pending);
    02048          strncat(bc->infos_pending,buf,l);
    02049          bc->infos_pending[l-1] = 0;
    02050       }
    02051       break;
    02052       case MISDN_CALLING_ACKNOWLEDGE:
    02053       {
    02054          bc->info_dad[0]=digit;
    02055          bc->info_dad[1]=0;
    02056
    02057          {
    02058             int l = sizeof(bc->dad);
    02059             strncat(bc->dad,bc->info_dad, l - strlen(bc->dad));
    02060             bc->dad[l-1] = 0;
    02061       }
    02062          {
    02063             int l = sizeof(p->ast->exten);
    02064             strncpy(p->ast->exten, bc->dad, l);
    02065             p->ast->exten[l-1] = 0;
    02066          }
    02067
    02068          misdn_lib_send_event( bc, EVENT_INFORMATION);
    02069       }
    02070       break;
    02071
    02072       default:
    02073          /* Do not send Digits in CONNECTED State, when
    02074           * the other side is too mISDN. */
    02075          if (p->other_ch )
    02076             return 0;
    02077
    02078          if ( bc->send_dtmf )
    02079             send_digit_to_chan(p,digit);
    02080       break;
    02081    }
    02082
    02083    return 0;
    02084 }
    02085
    02086
    02087 static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
    02088 {
    02089    struct chan_list *p;
    02090
    02091    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
    02092
    02093    chan_misdn_log(1, p->bc?p->bc->port:0, "* IND: Got Fixup State:%s L3id:%x\n", misdn_get_ch_state(p), p->l3id);
    02094
    02095    p->ast = ast ;
    02096
    02097    return 0;
    02098 }
    02099
    02100
    02101
    02102 static int misdn_indication(struct ast_channel *ast, int cond)
    02103 {
    02104    struct chan_list *p;
    02105
    02106
    02107    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
    02108       ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
    02109       return -1;
    02110    }
    02111
    02112    if (!p->bc ) {
    02113       chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
    02114       ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
    02115       return -1;
    02116    }
    02117
    02118    chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten);
    02119
    02120    switch (cond) {
    02121    case AST_CONTROL_BUSY:
    02122       chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n",p->bc?p->bc->pid:-1);
    02123       ast_setstate(ast,AST_STATE_BUSY);
    02124
    02125       p->bc->out_cause=17;
    02126       if (p->state != MISDN_CONNECTED) {
    02127          start_bc_tones(p);
    02128          misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
    02129       } else {
    02130          chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
    02131       }
    02132       return -1;
    02133       break;
    02134    case AST_CONTROL_RING:
    02135       chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
    02136       return -1;
    02137       break;
    02138
    02139    case AST_CONTROL_RINGING:
    02140       chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
    02141       switch (p->state) {
    02142          case MISDN_ALERTING:
    02143             chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
    02144             break;
    02145          case MISDN_CONNECTED:
    02146             chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n",p->bc?p->bc->pid:-1);
    02147             return -1;
    02148             break;
    02149          default:
    02150             p->state=MISDN_ALERTING;
    02151             chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
    02152             misdn_lib_send_event( p->bc, EVENT_ALERTING);
    02153
    02154             if (p->other_ch && p->other_ch->bc) {
    02155                if (misdn_inband_avail(p->other_ch->bc)) {
    02156                   chan_misdn_log(2,p->bc->port, " --> other End is mISDN and has inband info available\n");
    02157                   break;
    02158                }
    02159
    02160                if (!p->other_ch->bc->nt) {
    02161                   chan_misdn_log(2,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
    02162                   break;
    02163                }
    02164             }
    02165
    02166             chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
    02167             ast_setstate(ast,AST_STATE_RINGING);
    02168
    02169             if ( !p->bc->nt && (p->orginator==ORG_MISDN) && !p->incoming_early_audio )
    02170                chan_misdn_log(2,p->bc->port, " --> incoming_early_audio off\n");
    02171             else
    02172                return -1;
    02173       }
    02174       break;
    02175    case AST_CONTROL_ANSWER:
    02176       chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
    02177       start_bc_tones(p);
    02178       break;
    02179    case AST_CONTROL_TAKEOFFHOOK:
    02180       chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
    02181       return -1;
    02182       break;
    02183    case AST_CONTROL_OFFHOOK:
    02184       chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
    02185       return -1;
    02186       break;
    02187    case AST_CONTROL_FLASH:
    02188       chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
    02189       break;
    02190    case AST_CONTROL_PROGRESS:
    02191       chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
    02192       misdn_lib_send_event( p->bc, EVENT_PROGRESS);
    02193       break;
    02194    case AST_CONTROL_PROCEEDING:
    02195       chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n",p->bc?p->bc->pid:-1);
    02196       misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
    02197       break;
    02198    case AST_CONTROL_CONGESTION:
    02199       chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
    02200
    02201       p->bc->out_cause=42;
    02202       start_bc_tones(p);
    02203       misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
    02204
    02205       if (p->bc->nt) {
    02206          hanguptone_indicate(p);
    02207       }
    02208       break;
    02209    case -1 :
    02210       chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1);
    02211
    02212       stop_indicate(p);
    02213
    02214       if (p->state == MISDN_CONNECTED)
    02215          start_bc_tones(p);
    02216
    02217       break;
    02218
    02219    case AST_CONTROL_HOLD:
    02220       chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
    02221       break;
    02222    case AST_CONTROL_UNHOLD:
    02223       chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
    02224       break;
    02225    default:
    02226       chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
    02227    }
    02228
    02229    return 0;
    02230 }
    02231
    02232 static int misdn_hangup(struct ast_channel *ast)
    02233 {
    02234    struct chan_list *p;
    02235    struct misdn_bchannel *bc=NULL;
    02236
    02237    ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
    02238
    02239    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
    02240
    02241    if (!p) {
    02242       chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
    02243       return 0 ;
    02244    }
    02245
    02246    bc=p->bc;
    02247
    02248
    02249
    02250    MISDN_ASTERISK_TECH_PVT(ast)=NULL;
    02251    p->ast=NULL;
    02252
    02253    bc=p->bc;
    02254
    02255    if (ast->_state == AST_STATE_RESERVED ||
    02256       p->state == MISDN_NOTHING ||
    02257       p->state == MISDN_HOLDED ||
    02258       p->state == MISDN_HOLD_DISCONNECT ) {
    02259
    02260       CLEAN_CH:
    02261       /* between request and call */
    02262       ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n");
    02263       MISDN_ASTERISK_TECH_PVT(ast)=NULL;
    02264
    02265       cl_dequeue_chan(&cl_te, p);
    02266
    02267       close(p->pipe[0]);
    02268       close(p->pipe[1]);
    02269
    02270       free(p);
    02271       if (bc)
    02272          misdn_lib_release(bc);
    02273
    02274       return 0;
    02275    }
    02276
    02277    if (!bc) {
    02278       ast_log(LOG_WARNING,"Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
    02279       goto CLEAN_CH;
    02280    }
    02281
    02282
    02283    p->need_hangup=0;
    02284    p->need_queue_hangup=0;
    02285
    02286
    02287    if (!p->bc->nt)
    02288       stop_bc_tones(p);
    02289
    02290
    02291    {
    02292       const char *varcause=NULL;
    02293       bc->out_cause=ast->hangupcause?ast->hangupcause:16;
    02294
    02295       if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
    02296            (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
    02297          int tmpcause=atoi(varcause);
    02298          bc->out_cause=tmpcause?tmpcause:16;
    02299       }
    02300
    02301       chan_misdn_log(1, bc->port, "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n",p->bc?p->bc->pid:-1, ast->context, ast->exten, AST_CID_P(ast), misdn_get_ch_state(p));
    02302       chan_misdn_log(3, bc->port, " --> l3id:%x\n",p->l3id);
    02303       chan_misdn_log(3, bc->port, " --> cause:%d\n",bc->cause);
    02304       chan_misdn_log(2, bc->port, " --> out_cause:%d\n",bc->out_cause);
    02305       chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
    02306
    02307       switch (p->state) {
    02308       case MISDN_CALLING:
    02309       case MISDN_INCOMING_SETUP:
    02310          /* This is the only place in misdn_hangup, where we
    02311           * can call release_chan, else it might create lot's of trouble
    02312           * */
    02313          ast_log(LOG_NOTICE, "release channel, in CALLING/INCOMING_SETUP state.. no other events happened\n");
    02314          release_chan(bc);
    02315
    02316          p->state=MISDN_CLEANING;
    02317          misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
    02318          break;
    02319       case MISDN_HOLDED:
    02320       case MISDN_DIALING:
    02321          start_bc_tones(p);
    02322          hanguptone_indicate(p);
    02323
    02324          if (bc->need_disconnect)
    02325             misdn_lib_send_event( bc, EVENT_DISCONNECT);
    02326          break;
    02327
    02328       case MISDN_CALLING_ACKNOWLEDGE:
    02329          start_bc_tones(p);
    02330          hanguptone_indicate(p);
    02331
    02332          if (bc->need_disconnect)
    02333             misdn_lib_send_event( bc, EVENT_DISCONNECT);
    02334          break;
    02335
    02336       case MISDN_ALERTING:
    02337       case MISDN_PROGRESS:
    02338       case MISDN_PROCEEDING:
    02339          if (p->orginator != ORG_AST)
    02340             hanguptone_indicate(p);
    02341
    02342          /*p->state=MISDN_CLEANING;*/
    02343          if (bc->need_disconnect)
    02344             misdn_lib_send_event( bc, EVENT_DISCONNECT);
    02345          break;
    02346       case MISDN_CONNECTED:
    02347       case MISDN_PRECONNECTED:
    02348          /*  Alerting or Disconect */
    02349          if (p->bc->nt) {
    02350             start_bc_tones(p);
    02351             hanguptone_indicate(p);
    02352             p->bc->progress_indicator=8;
    02353          }
    02354          if (bc->need_disconnect)
    02355             misdn_lib_send_event( bc, EVENT_DISCONNECT);
    02356
    02357          /*p->state=MISDN_CLEANING;*/
    02358          break;
    02359       case MISDN_DISCONNECTED:
    02360          misdn_lib_send_event( bc, EVENT_RELEASE);
    02361          p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
    02362          break;
    02363
    02364       case MISDN_RELEASED:
    02365       case MISDN_CLEANING:
    02366          p->state=MISDN_CLEANING;
    02367          break;
    02368
    02369       case MISDN_BUSY:
    02370          break;
    02371
    02372       case MISDN_HOLD_DISCONNECT:
    02373          /* need to send release here */
    02374          chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
    02375          chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
    02376
    02377          bc->out_cause=-1;
    02378          misdn_lib_send_event(bc,EVENT_RELEASE);
    02379          p->state=MISDN_CLEANING;
    02380          break;
    02381       default:
    02382          if (bc->nt) {
    02383             bc->out_cause=-1;
    02384             misdn_lib_send_event(bc, EVENT_RELEASE);
    02385             p->state=MISDN_CLEANING;
    02386          } else {
    02387             if (bc->need_disconnect)
    02388                misdn_lib_send_event(bc, EVENT_DISCONNECT);
    02389          }
    02390       }
    02391
    02392       p->state=MISDN_CLEANING;
    02393
    02394    }
    02395
    02396
    02397    chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
    02398
    02399    return 0;
    02400 }
    02401
    02402 static struct ast_frame  *misdn_read(struct ast_channel *ast)
    02403 {
    02404    struct chan_list *tmp;
    02405    int len;
    02406
    02407    if (!ast) {
    02408       chan_misdn_log(1,0,"misdn_read called without ast\n");
    02409       return NULL;
    02410    }
    02411    if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) {
    02412       chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
    02413       return NULL;
    02414    }
    02415
    02416    if (!tmp->bc && !(tmp->state==MISDN_HOLDED)) {
    02417       chan_misdn_log(1,0,"misdn_read called without bc\n");
    02418       return NULL;
    02419    }
    02420
    02421    len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
    02422
    02423    if (len<=0) {
    02424       /* we hangup here, since our pipe is closed */
    02425       chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
    02426       return NULL;
    02427    }
    02428
    02429    tmp->frame.frametype  = AST_FRAME_VOICE;
    02430    tmp->frame.subclass = AST_FORMAT_ALAW;
    02431    tmp->frame.datalen = len;
    02432    tmp->frame.samples = len ;
    02433    tmp->frame.mallocd =0 ;
    02434    tmp->frame.offset= 0 ;
    02435    tmp->frame.delivery= ast_tv(0,0) ;
    02436    tmp->frame.src = NULL;
    02437    tmp->frame.data = tmp->ast_rd_buf ;
    02438
    02439    if (tmp->faxdetect || tmp->ast_dsp ) {
    02440       return process_ast_dsp(tmp, &tmp->frame);
    02441    }
    02442
    02443    return &tmp->frame;
    02444 }
    02445
    02446
    02447 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
    02448 {
    02449    struct chan_list *ch;
    02450    int i  = 0;
    02451
    02452    if (!ast || ! (ch=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
    02453
    02454    if (ch->state == MISDN_HOLDED) {
    02455       chan_misdn_log(8, 0, "misdn_write: Returning because holded\n");
    02456       return 0;
    02457    }
    02458
    02459    if (!ch->bc ) {
    02460
    02461       ast_log(LOG_WARNING, "private but no bc\n");
    02462       return -1;
    02463    }
    02464
    02465    if (ch->notxtone) {
    02466       chan_misdn_log(9, ch->bc->port, "misdn_write: Returning because notxone\n");
    02467       return 0;
    02468    }
    02469
    02470
    02471    if ( !frame->subclass) {
    02472       chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
    02473       return 0;
    02474    }
    02475
    02476    if ( !(frame->subclass & prefformat)) {
    02477
    02478       chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
    02479       return 0;
    02480    }
    02481
    02482
    02483    if ( !frame->samples ) {
    02484       chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
    02485
    02486       if (!strcmp(frame->src,"ast_prod")) {
    02487          chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
    02488
    02489          if (ch->ts) {
    02490             chan_misdn_log(4,ch->bc->port,"Starting Playtones\n");
    02491             misdn_lib_tone_generator_start(ch->bc);
    02492          }
    02493          return 0;
    02494       }
    02495
    02496       return -1;
    02497    }
    02498
    02499    if ( ! ch->bc->addr ) {
    02500       chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
    02501       return 0;
    02502    }
    02503
    02504 #if MISDN_DEBUG
    02505    {
    02506       int i, max=5>frame->samples?frame->samples:5;
    02507
    02508       printf("write2mISDN %p %d bytes: ", p, frame->samples);
    02509
    02510       for (i=0; i<  max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
    02511       printf ("\n");
    02512    }
    02513 #endif
    02514
    02515
    02516    switch (ch->bc->bc_state) {
    02517       case BCHAN_ACTIVATED:
    02518       case BCHAN_BRIDGED:
    02519          break;
    02520       default:
    02521       if (!ch->dropped_frame_cnt)
    02522          chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n",frame->samples,ch->bc->addr, ast->exten, ast->cid.cid_num,misdn_get_ch_state( ch), ch->bc->bc_state, ch->bc->l3_id);
    02523
    02524       ch->dropped_frame_cnt++;
    02525       if (ch->dropped_frame_cnt > 100) {
    02526          ch->dropped_frame_cnt=0;
    02527          chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x  dropped > 100 frames!\n",frame->samples,ch->bc->addr);
    02528
    02529       }
    02530
    02531       return 0;
    02532    }
    02533
    02534    chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n",frame->samples);
    02535
    02536    if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
    02537       /* Buffered Transmit (triggert by read from isdn side)*/
    02538       if (misdn_jb_fill(ch->jb,frame->data,frame->samples) < 0) {
    02539          if (ch->bc->active)
    02540             cb_log(0,ch->bc->port,"Misdn Jitterbuffer Overflow.\n");
    02541       }
    02542
    02543    } else {
    02544       /*transmit without jitterbuffer*/
    02545       i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
    02546    }
    02547
    02548
    02549
    02550    return 0;
    02551 }
    02552
    02553
    02554
    02555
    02556 enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
    02557                   struct ast_channel *c1, int flags,
    02558                   struct ast_frame **fo,
    02559                   struct ast_channel **rc,
    02560                   int timeoutms)
    02561
    02562 {
    02563    struct chan_list *ch1,*ch2;
    02564    struct ast_channel *carr[2], *who;
    02565    int to=-1;
    02566    struct ast_frame *f;
    02567
    02568    ch1=get_chan_by_ast(c0);
    02569    ch2=get_chan_by_ast(c1);
    02570
    02571    carr[0]=c0;
    02572    carr[1]=c1;
    02573
    02574    if (ch1 && ch2 ) ;
    02575    else
    02576       return -1;
    02577
    02578    int p1_b, p2_b;
    02579
    02580    misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(int));
    02581    misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(int));
    02582
    02583    if ( ! p1_b || ! p2_b) {
    02584       ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
    02585       return AST_BRIDGE_FAILED;
    02586    }
    02587
    02588    int bridging;
    02589    misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
    02590    if (bridging) {
    02591       /* trying to make a mISDN_dsp conference */
    02592       chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid +1);
    02593       misdn_lib_bridge(ch1->bc,ch2->bc);
    02594    }
    02595
    02596    chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
    02597
    02598
    02599    if (! (flags&AST_BRIDGE_DTMF_CHANNEL_0) )
    02600       ch1->ignore_dtmf=1;
    02601
    02602    if (! (flags&AST_BRIDGE_DTMF_CHANNEL_1) )
    02603       ch2->ignore_dtmf=1;
    02604
    02605
    02606    while(1) {
    02607       to=-1;
    02608       who = ast_waitfor_n(carr, 2, &to);
    02609
    02610       if (!who) {
    02611          ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
    02612          break;
    02613       }
    02614       f = ast_read(who);
    02615
    02616       if (!f || f->frametype == AST_FRAME_CONTROL) {
    02617          /* got hangup .. */
    02618
    02619          if (!f)
    02620             chan_misdn_log(4,ch1->bc->port,"Read Null Frame\n");
    02621          else
    02622             chan_misdn_log(4,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass);
    02623
    02624          *fo=f;
    02625          *rc=who;
    02626
    02627          break;
    02628       }
    02629
    02630       if ( f->frametype == AST_FRAME_DTMF ) {
    02631          chan_misdn_log(1,0,"Read DTMF %d from %s\n",f->subclass, who->exten);
    02632
    02633          *fo=f;
    02634          *rc=who;
    02635          break;
    02636       }
    02637
    02638 #if 0
    02639       if (f->frametype == AST_FRAME_VOICE) {
    02640          chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
    02641
    02642          continue;
    02643       }
    02644 #endif
    02645
    02646       if (who == c0) {
    02647          ast_write(c1,f);
    02648       }
    02649       else {
    02650          ast_write(c0,f);
    02651       }
    02652
    02653    }
    02654
    02655    chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
    02656
    02657    misdn_lib_split_bridge(ch1->bc,ch2->bc);
    02658
    02659
    02660    return AST_BRIDGE_COMPLETE;
    02661 }
    02662
    02663 /** AST INDICATIONS END **/
    02664
    02665 static int dialtone_indicate(struct chan_list *cl)
    02666 {
    02667    const struct tone_zone_sound *ts= NULL;
    02668    struct ast_channel *ast=cl->ast;
    02669
    02670    if (!ast) {
    02671       chan_misdn_log(0,cl->bc->port,"No Ast in dialtone_indicate\n");
    02672       return -1;
    02673    }
    02674
    02675    int nd=0;
    02676    misdn_cfg_get( cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
    02677
    02678    if (nd) {
    02679       chan_misdn_log(1,cl->bc->port,"Not sending Dialtone, because config wants it\n");
    02680       return 0;
    02681    }
    02682
    02683    chan_misdn_log(3,cl->bc->port," --> Dial\n");
    02684    ts=ast_get_indication_tone(ast->zone,"dial");
    02685    cl->ts=ts;
    02686
    02687    if (ts) {
    02688       cl->notxtone=0;
    02689       cl->norxtone=0;
    02690       /* This prods us in misdn_write */
    02691       ast_playtones_start(ast,0, ts->data, 0);
    02692    }
    02693
    02694    return 0;
    02695 }
    02696
    02697 static int hanguptone_indicate(struct chan_list *cl)
    02698 {
    02699    misdn_lib_send_tone(cl->bc,TONE_HANGUP);
    02700    return 0;
    02701 }
    02702
    02703 static int stop_indicate(struct chan_list *cl)
    02704 {
    02705    struct ast_channel *ast=cl->ast;
    02706
    02707    if (!ast) {
    02708       chan_misdn_log(0,cl->bc->port,"No Ast in stop_indicate\n");
    02709       return -1;
    02710    }
    02711
    02712    chan_misdn_log(3,cl->bc->port," --> None\n");
    02713    misdn_lib_tone_generator_stop(cl->bc);
    02714    ast_playtones_stop(ast);
    02715
    02716    cl->ts=NULL;
    02717    /*ast_deactivate_generator(ast);*/
    02718
    02719    return 0;
    02720 }
    02721
    02722
    02723 static int start_bc_tones(struct chan_list* cl)
    02724 {
    02725    misdn_lib_tone_generator_stop(cl->bc);
    02726    cl->notxtone=0;
    02727    cl->norxtone=0;
    02728    return 0;
    02729 }
    02730
    02731 static int stop_bc_tones(struct chan_list *cl)
    02732 {
    02733    if (!cl) return -1;
    02734
    02735    cl->notxtone=1;
    02736    cl->norxtone=1;
    02737
    02738    return 0;
    02739 }
    02740
    02741
    02742 static struct chan_list *init_chan_list(int orig)
    02743 {
    02744    struct chan_list *cl=malloc(sizeof(struct chan_list));
    02745
    02746    if (!cl) {
    02747       chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
    02748       return NULL;
    02749    }
    02750
    02751    memset(cl,0,sizeof(struct chan_list));
    02752
    02753    cl->orginator=orig;
    02754    cl->need_queue_hangup=1;
    02755    cl->need_hangup=1;
    02756    cl->need_busy=1;
    02757    cl->overlap_dial_task=-1;
    02758
    02759    return cl;
    02760
    02761 }
    02762
    02763 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
    02764
    02765 {
    02766    struct ast_channel *tmp = NULL;
    02767    char group[BUFFERSIZE+1]="";
    02768    char buf[128];
    02769    char buf2[128], *ext=NULL, *port_str;
    02770    char *tokb=NULL, *p=NULL;
    02771    int channel=0, port=0;
    02772    struct misdn_bchannel *newbc = NULL;
    02773    int dec=0;
    02774
    02775    struct chan_list *cl=init_chan_list(ORG_AST);
    02776
    02777    sprintf(buf,"%s/%s",misdn_type,(char*)data);
    02778    ast_copy_string(buf2,data, 128);
    02779
    02780    port_str=strtok_r(buf2,"/", &tokb);
    02781
    02782    ext=strtok_r(NULL,"/", &tokb);
    02783
    02784    if (port_str) {
    02785       if (port_str[0]=='g' && port_str[1]==':' ) {
    02786          /* We make a group call lets checkout which ports are in my group */
    02787          port_str += 2;
    02788          strncpy(group, port_str, BUFFERSIZE);
    02789          group[127] = 0;
    02790          chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
    02791       }
    02792       else if ((p = strchr(port_str, ':'))) {
    02793          /* we have a preselected channel */
    02794          *p = 0;
    02795          channel = atoi(++p);
    02796          port = atoi(port_str);
    02797          chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
    02798       }
    02799       else {
    02800          port = atoi(port_str);
    02801       }
    02802    } else {
    02803       ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
    02804       return NULL;
    02805    }
    02806
    02807    if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
    02808       chan_misdn_log(4, port, " --> STARTING STANDARDDEC...\n");
    02809       dec=1;
    02810    }
    02811
    02812    if (!ast_strlen_zero(group)) {
    02813
    02814       char cfg_group[BUFFERSIZE+1];
    02815       struct robin_list *rr = NULL;
    02816
    02817       if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
    02818          chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
    02819          rr = get_robin_position(group);
    02820       }
    02821
    02822
    02823       if (rr) {
    02824          int robin_channel = rr->channel;
    02825          int port_start;
    02826          int next_chan = 1;
    02827
    02828          do {
    02829             port_start = 0;
    02830             for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
    02831                 port = misdn_cfg_get_next_port_spin(port)) {
    02832
    02833                if (!port_start)
    02834                   port_start = port;
    02835
    02836                if (port >= port_start)
    02837                   next_chan = 1;
    02838
    02839                if (port <= port_start && next_chan) {
    02840                   int maxbchans=misdn_lib_get_maxchans(port);
    02841                   if (++robin_channel >= maxbchans) {
    02842                      robin_channel = 1;
    02843                   }
    02844                   next_chan = 0;
    02845                }
    02846
    02847                misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
    02848
    02849                if (!strcasecmp(cfg_group, group)) {
    02850                   int port_up;
    02851                   int check;
    02852                   misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
    02853                   port_up = misdn_lib_port_up(port, check);
    02854
    02855                   if (check && !port_up)
    02856                      chan_misdn_log(1,port,"L1 is not Up on this Port\n");
    02857
    02858                   if (check && port_up<0) {
    02859                      ast_log(LOG_WARNING,"This port (%d) is blocked\n", port);
    02860                   }
    02861
    02862
    02863                   if ( port_up>0 )  {
    02864                      newbc = misdn_lib_get_free_bc(port, robin_channel,0, 0);
    02865                      if (newbc) {
    02866                         chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
    02867                         if (port_up)
    02868                            chan_misdn_log(4, port, "portup:%d\n",  port_up);
    02869                         rr->port = newbc->port;
    02870                         rr->channel = newbc->channel;
    02871                         break;
    02872                      }
    02873                   }
    02874                }
    02875             }
    02876          } while (!newbc && robin_channel != rr->channel);
    02877
    02878       } else {
    02879          for (port=misdn_cfg_get_next_port(0); port > 0;
    02880              port=misdn_cfg_get_next_port(port)) {
    02881
    02882             misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
    02883
    02884             chan_misdn_log(3,port, "Group [%s] Port [%d]\n", group, port);
    02885             if (!strcasecmp(cfg_group, group)) {
    02886                int port_up;
    02887                int check;
    02888                misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
    02889                port_up = misdn_lib_port_up(port, check);
    02890
    02891                chan_misdn_log(4, port, "portup:%d\n", port_up);
    02892
    02893                if ( port_up>0 ) {
    02894                   newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
    02895                   if (newbc)
    02896                      break;
    02897                }
    02898             }
    02899          }
    02900       }
    02901
    02902       /* Group dial failed ?*/
    02903       if (!newbc) {
    02904          ast_log(LOG_WARNING,
    02905                "Could not Dial out on group '%s'.\n"
    02906                "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
    02907                "\tOr there was no free channel on none of the ports\n\n"
    02908                , group);
    02909          return NULL;
    02910       }
    02911    } else { /* 'Normal' Port dial * Port dial */
    02912       if (channel)
    02913          chan_misdn_log(1, port," --> preselected_channel: %d\n",channel);
    02914       newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
    02915
    02916       if (!newbc) {
    02917          ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n",port,ext);
    02918          return NULL;
    02919       }
    02920    }
    02921
    02922
    02923    /* create ast_channel and link all the objects together */
    02924    cl->bc=newbc;
    02925
    02926    tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
    02927    if (!tmp) {
    02928       ast_log(LOG_ERROR,"Could not create Asterisk object\n");
    02929       return NULL;
    02930    }
    02931
    02932    cl->ast=tmp;
    02933
    02934    /* register chan in local list */
    02935    cl_queue_chan(&cl_te, cl) ;
    02936
    02937    /* fill in the config into the objects */
    02938    read_config(cl, ORG_AST);
    02939
    02940    /* important */
    02941    cl->need_hangup=0;
    02942
    02943    return tmp;
    02944 }
    02945
    02946
    02947 int misdn_send_text (struct ast_channel *chan, const char *text)
    02948 {
    02949    struct chan_list *tmp=chan->tech_pvt;
    02950
    02951    if (tmp && tmp->bc) {
    02952       ast_copy_string(tmp->bc->display,text,sizeof(tmp->bc->display));
    02953       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
    02954    } else {
    02955       ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
    02956       return -1;
    02957    }
    02958
    02959    return 0;
    02960 }
    02961
    02962 static struct ast_channel_tech misdn_tech = {
    02963    .type="mISDN",
    02964    .description="Channel driver for mISDN Support (Bri/Pri)",
    02965    .capabilities= AST_FORMAT_ALAW ,
    02966    .requester=misdn_request,
    02967    .send_digit=misdn_digit,
    02968    .call=misdn_call,
    02969    .bridge=misdn_bridge,
    02970    .hangup=misdn_hangup,
    02971    .answer=misdn_answer,
    02972    .read=misdn_read,
    02973    .write=misdn_write,
    02974    .indicate=misdn_indication,
    02975    .fixup=misdn_fixup,
    02976    .send_text=misdn_send_text,
    02977    .properties=0
    02978 };
    02979
    02980 static struct ast_channel_tech misdn_tech_wo_bridge = {
    02981    .type="mISDN",
    02982    .description="Channel driver for mISDN Support (Bri/Pri)",
    02983    .capabilities=AST_FORMAT_ALAW ,
    02984    .requester=misdn_request,
    02985    .send_digit=misdn_digit,
    02986    .call=misdn_call,
    02987    .hangup=misdn_hangup,
    02988    .answer=misdn_answer,
    02989    .read=misdn_read,
    02990    .write=misdn_write,
    02991    .indicate=misdn_indication,
    02992    .fixup=misdn_fixup,
    02993    .send_text=misdn_send_text,
    02994    .properties=0
    02995 };
    02996
    02997
    02998 static unsigned long glob_channel=0;
    02999
    03000 static struct ast_channel *misdn_new(struct chan_list *chlist, int state,  char *exten, char *callerid, int format, int port, int c)
    03001 {
    03002    struct ast_channel *tmp;
    03003
    03004    tmp = ast_channel_alloc(1);
    03005
    03006    if (tmp) {
    03007       chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid);
    03008
    03009
    03010       if (c<=0) {
    03011          c=glob_channel++;
    03012          snprintf(tmp->name, sizeof(tmp->name), "%s/%d-u%d",
    03013              misdn_type, port, c);
    03014       } else {
    03015          snprintf(tmp->name, sizeof(tmp->name), "%s/%d-%d",
    03016              misdn_type, port, c);
    03017       }
    03018
    03019       tmp->type = misdn_type;
    03020
    03021       tmp->nativeformats = prefformat;
    03022
    03023       tmp->readformat = format;
    03024       tmp->rawreadformat = format;
    03025       tmp->writeformat = format;
    03026       tmp->rawwriteformat = format;
    03027
    03028       tmp->tech_pvt = chlist;
    03029
    03030       int bridging;
    03031       misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
    03032
    03033       if (bridging)
    03034          tmp->tech = &misdn_tech;
    03035       else
    03036          tmp->tech = &misdn_tech_wo_bridge;
    03037
    03038       tmp->writeformat = format;
    03039       tmp->readformat = format;
    03040       tmp->priority=1;
    03041
    03042       if (exten)
    03043          ast_copy_string(tmp->exten, exten,  sizeof(tmp->exten));
    03044       else
    03045          chan_misdn_log(1,0,"misdn_new: no exten given.\n");
    03046
    03047       if (callerid) {
    03048          char *cid_name, *cid_num;
    03049
    03050          ast_callerid_parse(callerid, &cid_name, &cid_num);
    03051
    03052          if (!ast_strlen_zero(cid_num))
    03053             tmp->cid.cid_num = strdup(cid_num);
    03054          if (!ast_strlen_zero(cid_name))
    03055             tmp->cid.cid_name = strdup(cid_name);
    03056       }
    03057
    03058       {
    03059          if (pipe(chlist->pipe)<0)
    03060             perror("Pipe failed\n");
    03061
    03062          tmp->fds[0]=chlist->pipe[0];
    03063
    03064       }
    03065
    03066       ast_setstate(tmp, state);
    03067       if (state == AST_STATE_RING)
    03068          tmp->rings = 1;
    03069       else
    03070          tmp->rings = 0;
    03071
    03072
    03073    } else {
    03074       chan_misdn_log(-1,0,"Unable to allocate channel structure\n");
    03075    }
    03076
    03077    return tmp;
    03078 }
    03079
    03080
    03081 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
    03082 {
    03083    struct ast_frame *f,*f2;
    03084    if (tmp->trans)
    03085       f2=ast_translate(tmp->trans, frame,0);
    03086    else {
    03087       chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
    03088       return NULL;
    03089    }
    03090
    03091    f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
    03092    if (f && (f->frametype == AST_FRAME_DTMF)) {
    03093       ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c\n", f->subclass);
    03094       if (f->subclass == 'f' && tmp->faxdetect) {
    03095          /* Fax tone -- Handle and return NULL */
    03096          struct ast_channel *ast = tmp->ast;
    03097          if (!tmp->faxhandled) {
    03098             tmp->faxhandled++;
    03099             if (strcmp(ast->exten, "fax")) {
    03100                if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
    03101                   if (option_verbose > 2)
    03102                      ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
    03103                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
    03104                   pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
    03105                   if (ast_async_goto(ast, ast->context, "fax", 1))
    03106                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
    03107                } else
    03108                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
    03109             } else
    03110                ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
    03111          } else
    03112             ast_log(LOG_DEBUG, "Fax already handled\n");
    03113
    03114       }  else if ( tmp->ast_dsp) {
    03115          chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
    03116          return f;
    03117       }
    03118    }
    03119
    03120    frame->frametype = AST_FRAME_NULL;
    03121    frame->subclass = 0;
    03122    return frame;
    03123 }
    03124
    03125
    03126 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
    03127 {
    03128    struct chan_list *help=list;
    03129    for (;help; help=help->next) {
    03130       if (help->bc == bc) return help;
    03131    }
    03132
    03133    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
    03134
    03135    return NULL;
    03136 }
    03137
    03138 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
    03139 {
    03140    struct chan_list *help=list;
    03141    for (;help; help=help->next) {
    03142       if ( help->bc && (help->bc->pid == pid) ) return help;
    03143    }
    03144
    03145    chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid);
    03146
    03147    return NULL;
    03148 }
    03149
    03150 static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
    03151 {
    03152    struct chan_list *help=list;
    03153
    03154    if (bc->pri) return NULL;
    03155
    03156    chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
    03157    for (;help; help=help->next) {
    03158       chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->state==MISDN_HOLDED, help->hold_info.channel);
    03159       if (help->hold_info.port == bc->port
    03160       ) return help;
    03161    }
    03162
    03163    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
    03164
    03165    return NULL;
    03166 }
    03167
    03168
    03169 static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w)
    03170
    03171 {
    03172    struct chan_list *help=list;
    03173
    03174    for (;help; help=help->next) {
    03175       if ( (help->state == MISDN_HOLDED) &&
    03176           (help->l3id == l3_id)
    03177          )
    03178          return help;
    03179    }
    03180
    03181    return NULL;
    03182 }
    03183
    03184 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
    03185 {
    03186    chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
    03187
    03188    ast_mutex_lock(&cl_te_lock);
    03189    if (!*list) {
    03190       *list = chan;
    03191    } else {
    03192       struct chan_list *help=*list;
    03193       for (;help->next; help=help->next);
    03194       help->next=chan;
    03195    }
    03196    chan->next=NULL;
    03197    ast_mutex_unlock(&cl_te_lock);
    03198 }
    03199
    03200 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
    03201 {
    03202    if (chan->dsp)
    03203       ast_dsp_free(chan->dsp);
    03204    if (chan->trans)
    03205       ast_translator_free_path(chan->trans);
    03206
    03207
    03208
    03209    ast_mutex_lock(&cl_te_lock);
    03210    if (!*list) {
    03211       ast_mutex_unlock(&cl_te_lock);
    03212       return;
    03213    }
    03214
    03215    if (*list == chan) {
    03216       *list=(*list)->next;
    03217       ast_mutex_unlock(&cl_te_lock);
    03218       return ;
    03219    }
    03220
    03221    {
    03222       struct chan_list *help=*list;
    03223       for (;help->next; help=help->next) {
    03224          if (help->next == chan) {
    03225             help->next=help->next->next;
    03226             ast_mutex_unlock(&cl_te_lock);
    03227             return;
    03228          }
    03229       }
    03230    }
    03231
    03232    ast_mutex_unlock(&cl_te_lock);
    03233 }
    03234
    03235 /** Channel Queue End **/
    03236
    03237
    03238 static int pbx_start_chan(struct chan_list *ch)
    03239 {
    03240    int ret=ast_pbx_start(ch->ast);
    03241
    03242    if (ret>=0)
    03243       ch->need_hangup=0;
    03244    else
    03245       ch->need_hangup=1;
    03246
    03247    return ret;
    03248 }
    03249
    03250 static void hangup_chan(struct chan_list *ch)
    03251 {
    03252    int port=ch?ch->bc?ch->bc->port:0:0;
    03253    if (!ch) {
    03254       cb_log(1,0,"Cannot hangup chan, no ch\n");
    03255       return;
    03256    }
    03257
    03258    cb_log(5,port,"hangup_chan called\n");
    03259
    03260    if (ch->need_hangup)
    03261    {
    03262       cb_log(2,port," --> hangup\n");
    03263       send_cause2ast(ch->ast,ch->bc,ch);
    03264       ch->need_hangup=0;
    03265       ch->need_queue_hangup=0;
    03266       if (ch->ast)
    03267          ast_hangup(ch->ast);
    03268       return;
    03269    }
    03270
    03271    if (!ch->need_queue_hangup) {
    03272       cb_log(2,port," --> No need to queue hangup\n");
    03273    }
    03274
    03275    ch->need_queue_hangup=0;
    03276    if (ch->ast) {
    03277       send_cause2ast(ch->ast,ch->bc,ch);
    03278
    03279       if (ch->ast)
    03280          ast_queue_hangup(ch->ast);
    03281       cb_log(2,port," --> queue_hangup\n");
    03282    } else {
    03283       cb_log(1,port,"Cannot hangup chan, no ast\n");
    03284    }
    03285 }
    03286
    03287 /** Isdn asks us to release channel, pendant to misdn_hangup **/
    03288 static void release_chan(struct misdn_bchannel *bc) {
    03289    struct ast_channel *ast=NULL;
    03290
    03291    ast_mutex_lock(&release_lock);
    03292    {
    03293       struct chan_list *ch=find_chan_by_bc(cl_te, bc);
    03294       if (!ch)  {
    03295          chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
    03296          ast_mutex_unlock(&release_lock);
    03297          return;
    03298       }
    03299
    03300       if (ch->ast) {
    03301          ast=ch->ast;
    03302       }
    03303
    03304       chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id);
    03305
    03306       /*releaseing jitterbuffer*/
    03307       if (ch->jb ) {
    03308          misdn_jb_destroy(ch->jb);
    03309          ch->jb=NULL;
    03310       } else {
    03311          if (!bc->nojitter)
    03312             chan_misdn_log(5,bc->port,"Jitterbuffer already destroyed.\n");
    03313       }
    03314
    03315       if (ch->overlap_dial) {
    03316          if (ch->overlap_dial_task != -1) {
    03317             misdn_tasks_remove(ch->overlap_dial_task);
    03318             ch->overlap_dial_task = -1;
    03319          }
    03320          ast_mutex_destroy(&ch->overlap_tv_lock);
    03321       }
    03322       if (ch) {
    03323
    03324          close(ch->pipe[0]);
    03325          close(ch->pipe[1]);
    03326
    03327
    03328          if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
    03329             chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n",bc?bc->pid:-1, ast->context, ast->exten,AST_CID_P(ast),misdn_get_ch_state(ch));
    03330             chan_misdn_log(3, bc->port, " --> * State Down\n");
    03331             MISDN_ASTERISK_TECH_PVT(ast)=NULL;
    03332
    03333
    03334             if (ast->_state != AST_STATE_RESERVED) {
    03335                chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
    03336                ast_setstate(ast, AST_STATE_DOWN);
    03337             }
    03338          }
    03339
    03340          ch->state=MISDN_CLEANING;
    03341          cl_dequeue_chan(&cl_te, ch);
    03342
    03343          free(ch);
    03344       } else {
    03345          /* chan is already cleaned, so exiting  */
    03346       }
    03347    }
    03348
    03349    ast_mutex_unlock(&release_lock);
    03350 }
    03351 /*** release end **/
    03352
    03353 static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
    03354 {
    03355    chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
    03356
    03357    tmp_ch->state=MISDN_HOLD_DISCONNECT;
    03358
    03359    ast_moh_stop(AST_BRIDGED_P(holded_chan->ast));
    03360
    03361    holded_chan->state=MISDN_CONNECTED;
    03362    //misdn_lib_transfer(holded_chan->bc);
    03363    ast_channel_masquerade(holded_chan->ast, AST_BRIDGED_P(tmp_ch->ast));
    03364 }
    03365
    03366
    03367 static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
    03368 {
    03369    char predial[256]="";
    03370    char *p = predial;
    03371
    03372    struct ast_frame fr;
    03373
    03374    strncpy(predial, ast->exten, sizeof(predial) -1 );
    03375
    03376    ch->state=MISDN_DIALING;
    03377
    03378    if (!ch->noautorespond_on_setup) {
    03379       if (bc->nt) {
    03380          int ret;
    03381          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
    03382       } else {
    03383          int ret;
    03384          if ( misdn_lib_is_ptp(bc->port)) {
    03385             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
    03386          } else {
    03387             ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
    03388          }
    03389       }
    03390    } else {
    03391       ch->state = MISDN_INCOMING_SETUP;
    03392    }
    03393
    03394    chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, AST_CID_P(ast));
    03395
    03396    strncpy(ast->exten,"s", 2);
    03397
    03398    if (pbx_start_chan(ch)<0) {
    03399       ast=NULL;
    03400       hangup_chan(ch);
    03401       hanguptone_indicate(ch);
    03402
    03403       if (bc->nt)
    03404          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
    03405       else
    03406          misdn_lib_send_event(bc, EVENT_DISCONNECT );
    03407    }
    03408
    03409
    03410    while (!ast_strlen_zero(p) ) {
    03411       fr.frametype = AST_FRAME_DTMF;
    03412       fr.subclass = *p ;
    03413       fr.src=NULL;
    03414       fr.data = NULL ;
    03415       fr.datalen = 0;
    03416       fr.samples = 0 ;
    03417       fr.mallocd =0 ;
    03418       fr.offset= 0 ;
    03419       fr.delivery= ast_tv(0,0) ;
    03420
    03421       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
    03422          ast_queue_frame(ch->ast, &fr);
    03423       }
    03424       p++;
    03425    }
    03426 }
    03427
    03428
    03429
    03430 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch) {
    03431    if (!ast) {
    03432       chan_misdn_log(1,0,"send_cause2ast: No Ast\n");
    03433       return;
    03434    }
    03435    if (!bc) {
    03436       chan_misdn_log(1,0,"send_cause2ast: No BC\n");
    03437       return;
    03438    }
    03439    if (!ch) {
    03440       chan_misdn_log(1,0,"send_cause2ast: No Ch\n");
    03441       return;
    03442    }
    03443
    03444    ast->hangupcause=bc->cause;
    03445
    03446    switch ( bc->cause) {
    03447
    03448    case 1: /** Congestion Cases **/
    03449    case 2:
    03450    case 3:
    03451    case 4:
    03452    case 22:
    03453    case 27:
    03454       /*
    03455        * Not Queueing the Congestion anymore, since we want to hear
    03456        * the inband message
    03457        *
    03458       chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
    03459       ch->state=MISDN_BUSY;
    03460
    03461       ast_queue_control(ast, AST_CONTROL_CONGESTION);
    03462       */
    03463       break;
    03464
    03465    case 21:
    03466    case 17: /* user busy */
    03467
    03468       ch->state=MISDN_BUSY;
    03469
    03470       if (!ch->need_busy) {
    03471          chan_misdn_log(1,bc?bc->port:0, "Queued busy already\n");
    03472          break;
    03473       }
    03474
    03475       chan_misdn_log(1,  bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
    03476
    03477       ast_queue_control(ast, AST_CONTROL_BUSY);
    03478
    03479       ch->need_busy=0;
    03480
    03481       break;
    03482    }
    03483 }
    03484
    03485 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
    03486 {
    03487    char *tmp;
    03488    tmp=pbx_builtin_getvar_helper(chan,"MISDN_PID");
    03489    if (tmp) {
    03490       ch->other_pid=atoi(tmp);
    03491       chan_misdn_log(3,bc->port," --> IMPORT_PID: importing pid:%s\n",tmp);
    03492
    03493       if (ch->other_pid >0) {
    03494          ch->other_ch=find_chan_by_pid(cl_te,ch->other_pid);
    03495          if (ch->other_ch) ch->other_ch->other_ch=ch;
    03496       }
    03497    }
    03498
    03499    tmp=pbx_builtin_getvar_helper(chan,"MISDN_ADDRESS_COMPLETE");
    03500    if (tmp && (atoi(tmp) == 1)) {
    03501       bc->sending_complete=1;
    03502    }
    03503
    03504    const char *kp=pbx_builtin_getvar_helper(chan,"MISDN_KEYPAD");
    03505    if (kp) {
    03506       strncpy(bc->keypad,kp,sizeof(bc->keypad));
    03507       bc->keypad[sizeof(bc->keypad)-1]=0;
    03508    }
    03509
    03510
    03511 }
    03512
    03513 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
    03514 {
    03515    char tmp[32];
    03516
    03517    chan_misdn_log(3,bc->port," --> EXPORT_PID: pid:%d\n",bc->pid);
    03518    sprintf(tmp,"%d",bc->pid);
    03519    pbx_builtin_setvar_helper(chan,"_MISDN_PID",tmp);
    03520
    03521    if (bc->sending_complete) {
    03522       sprintf(tmp,"%d",bc->sending_complete);
    03523       pbx_builtin_setvar_helper(chan,"MISDN_ADDRESS_COMPLETE",tmp);
    03524    }
    03525
    03526    if (bc->urate) {
    03527       sprintf(tmp,"%d",bc->urate);
    03528       pbx_builtin_setvar_helper(chan,"MISDN_URATE",tmp);
    03529    }
    03530
    03531    if (bc->keypad[0])
    03532       pbx_builtin_setvar_helper(chan,"MISDN_KEYPAD",bc->keypad);
    03533 }
    03534
    03535
    03536 static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
    03537    if (pbx_start_chan(ch)<0) {
    03538       hangup_chan(ch);
    03539       chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
    03540       if (bc->nt) {
    03541          hanguptone_indicate(ch);
    03542          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
    03543       } else
    03544          misdn_lib_send_event(bc, EVENT_RELEASE);
    03545    }
    03546 }
    03547
    03548 static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
    03549    ch->state=MISDN_WAITING4DIGS;
    03550    misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
    03551    if (bc->nt && !bc->dad[0])
    03552       dialtone_indicate(ch);
    03553 }
    03554
    03555
    03556
    03557 /************************************************************/
    03558 /*  Receive Events from isdn_lib  here                     */
    03559 /************************************************************/
    03560 static enum event_response_e
    03561 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
    03562 {
    03563    struct chan_list *ch=find_chan_by_bc(cl_te, bc);
    03564
    03565    if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /*  Debug Only Non-Bchan */
    03566       int debuglevel=1;
    03567       if ( event==EVENT_CLEANUP && !user_data)
    03568          debuglevel=5;
    03569
    03570       chan_misdn_log(debuglevel, bc->port, "I IND :%s oad:%s dad:%s pid:%d state:%s\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->pid, ch?misdn_get_ch_state(ch):"none");
    03571       if (debuglevel==1) {
    03572          misdn_lib_log_ies(bc);
    03573          chan_misdn_log(4,bc->port," --> bc_state:%s\n",bc_state2str(bc->bc_state));
    03574       }
    03575    }
    03576
    03577    if (!ch) {
    03578       switch(event) {
    03579          case EVENT_SETUP:
    03580          case EVENT_DISCONNECT:
    03581          case EVENT_PORT_ALARM:
    03582          case EVENT_RETRIEVE:
    03583          case EVENT_NEW_BC:
    03584             break;
    03585          case EVENT_RELEASE_COMPLETE:
    03586             chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
    03587             break;
    03588          case EVENT_CLEANUP:
    03589          case EVENT_TONE_GENERATE:
    03590          case EVENT_BCHAN_DATA:
    03591             return -1;
    03592
    03593          default:
    03594             chan_misdn_log(1,bc->port, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n",bc->l3_id, bc, manager_isdn_get_info( event), bc->port,bc->channel);
    03595             return -1;
    03596       }
    03597    }
    03598
    03599    if (ch ) {
    03600       switch (event) {
    03601       case EVENT_TONE_GENERATE:
    03602       break;
    03603       case EVENT_DISCONNECT:
    03604       case EVENT_RELEASE:
    03605       case EVENT_RELEASE_COMPLETE:
    03606       case EVENT_CLEANUP:
    03607       case EVENT_TIMEOUT:
    03608          if (!ch->ast)
    03609             chan_misdn_log(3,bc->port,"ast_hangup already called, so we have no ast ptr anymore in event(%s)\n",manager_isdn_get_info(event));
    03610          break;
    03611       default:
    03612          if ( !ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
    03613             if (event!=EVENT_BCHAN_DATA)
    03614                ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
    03615             return -1;
    03616          }
    03617       }
    03618    }
    03619
    03620
    03621    switch (event) {
    03622    case EVENT_PORT_ALARM:
    03623       {
    03624          int boa=0;
    03625
    03626          misdn_cfg_get( bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(int));
    03627          if (boa) {
    03628             cb_log(1,bc->port," --> blocking\n");
    03629             misdn_lib_port_block(bc->port);
    03630          }
    03631       }
    03632       break;
    03633
    03634    case EVENT_BCHAN_ACTIVATED:
    03635       break;
    03636
    03637    case EVENT_NEW_L3ID:
    03638       ch->l3id=bc->l3_id;
    03639       ch->addr=bc->addr;
    03640       break;
    03641
    03642    case EVENT_NEW_BC:
    03643       if (!ch) {
    03644          ch=find_holded(cl_te,bc);
    03645       }
    03646
    03647       if (!ch) {
    03648          ast_log(LOG_WARNING,"NEW_BC without chan_list?\n");
    03649          break;
    03650       }
    03651
    03652       if (bc)
    03653          ch->bc=(struct misdn_bchannel*)user_data;
    03654       break;
    03655
    03656    case EVENT_DTMF_TONE:
    03657    {
    03658       /*  sending INFOS as DTMF-Frames :) */
    03659       struct ast_frame fr;
    03660       memset(&fr, 0 , sizeof(fr));
    03661       fr.frametype = AST_FRAME_DTMF;
    03662       fr.subclass = bc->dtmf ;
    03663       fr.src=NULL;
    03664       fr.data = NULL ;
    03665       fr.datalen = 0;
    03666       fr.samples = 0 ;
    03667       fr.mallocd =0 ;
    03668       fr.offset= 0 ;
    03669       fr.delivery= ast_tv(0,0) ;
    03670
    03671       if (!ch->ignore_dtmf) {
    03672          chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
    03673          ast_queue_frame(ch->ast, &fr);
    03674       } else {
    03675          chan_misdn_log(2, bc->port, " --> Ingoring DTMF:%c due to bridge flags\n", bc->dtmf);
    03676       }
    03677    }
    03678    break;
    03679    case EVENT_STATUS:
    03680       break;
    03681
    03682    case EVENT_INFORMATION:
    03683    {
    03684       int l;
    03685
    03686       if ( ch->state != MISDN_CONNECTED )
    03687          stop_indicate(ch);
    03688
    03689       if (!ch->ast) break;
    03690
    03691       if (ch->state == MISDN_WAITING4DIGS ) {
    03692          /*  Ok, incomplete Setup, waiting till extension exists */
    03693          if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
    03694             chan_misdn_log(1, bc->port, " --> using keypad as info\n");
    03695             strcpy(bc->info_dad,bc->keypad);
    03696          }
    03697
    03698          l = sizeof(bc->dad);
    03699          strncat(bc->dad,bc->info_dad, l);
    03700          bc->dad[l-1] = 0;
    03701
    03702          l = sizeof(ch->ast->exten);
    03703          strncpy(ch->ast->exten, bc->dad, l);
    03704          ch->ast->exten[l-1] = 0;
    03705
    03706          /* Check for Pickup Request first */
    03707          if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
    03708             if (ast_pickup_call(ch->ast)) {
    03709                hangup_chan(ch);
    03710             } else {
    03711                struct ast_channel *chan=ch->ast;
    03712                ch->state = MISDN_CALLING_ACKNOWLEDGE;
    03713                ast_setstate(chan, AST_STATE_DOWN);
    03714                hangup_chan(ch);
    03715                ch->ast=NULL;
    03716                break;
    03717             }
    03718          }
    03719
    03720          if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
    03721             if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
    03722                ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n",bc->port);
    03723                strcpy(ch->ast->exten, "i");
    03724
    03725                ch->state = MISDN_DIALING;
    03726                start_pbx(ch, bc, ch->ast);
    03727                break;
    03728             }
    03729
    03730             ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d)."
    03731                   "maybe you want to add an 'i' extension to catch this case.\n",
    03732                   bc->port);
    03733
    03734             if (bc->nt)
    03735                hanguptone_indicate(ch);
    03736             ch->state=MISDN_EXTCANTMATCH;
    03737             bc->out_cause=1;
    03738
    03739             misdn_lib_send_event(bc, EVENT_DISCONNECT );
    03740             break;
    03741          }
    03742
    03743          if (ch->overlap_dial) {
    03744             ast_mutex_lock(&ch->overlap_tv_lock);
    03745             ch->overlap_tv = ast_tvnow();
    03746             ast_mutex_unlock(&ch->overlap_tv_lock);
    03747             if (ch->overlap_dial_task == -1) {
    03748                ch->overlap_dial_task =
    03749                   misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
    03750             }
    03751             break;
    03752          }
    03753
    03754          if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
    03755
    03756             ch->state = MISDN_DIALING;
    03757             start_pbx(ch, bc, ch->ast);
    03758          }
    03759       } else {
    03760          /*  sending INFOS as DTMF-Frames :) */
    03761          struct ast_frame fr;
    03762          fr.frametype = AST_FRAME_DTMF;
    03763          fr.subclass = bc->info_dad[0] ;
    03764          fr.src=NULL;
    03765          fr.data = NULL ;
    03766          fr.datalen = 0;
    03767          fr.samples = 0 ;
    03768          fr.mallocd =0 ;
    03769          fr.offset= 0 ;
    03770          fr.delivery= ast_tv(0,0) ;
    03771
    03772
    03773          int digits;
    03774          misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
    03775          if (ch->state != MISDN_CONNECTED ) {
    03776             if (digits) {
    03777                int l = sizeof(bc->dad);
    03778                strncat(bc->dad,bc->info_dad, l);
    03779                bc->dad[l-1] = 0;
    03780                l = sizeof(ch->ast->exten);
    03781                strncpy(ch->ast->exten, bc->dad, l);
    03782                ch->ast->exten[l-1] = 0;
    03783
    03784                ast_cdr_update(ch->ast);
    03785             }
    03786
    03787             ast_queue_frame(ch->ast, &fr);
    03788          }
    03789       }
    03790    }
    03791    break;
    03792    case EVENT_SETUP:
    03793    {
    03794       struct chan_list *ch=find_chan_by_bc(cl_te, bc);
    03795       if (ch) {
    03796          switch (ch->state) {
    03797             case MISDN_NOTHING:
    03798             ch=NULL;
    03799             break;
    03800             default:
    03801             chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
    03802             return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
    03803          }
    03804       }
    03805    }
    03806
    03807    {
    03808       int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
    03809       if (!bc->nt && ! msn_valid) {
    03810          chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
    03811          return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
    03812       }
    03813
    03814       if (bc->cw) {
    03815          chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
    03816          int cause;
    03817          misdn_cfg_get( bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
    03818          bc->out_cause=cause?cause:16;
    03819          return RESPONSE_RELEASE_SETUP;
    03820       }
    03821
    03822       print_bearer(bc);
    03823
    03824       struct chan_list *ch=init_chan_list(ORG_MISDN);
    03825       struct ast_channel *chan;
    03826
    03827       if (!ch) { chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
    03828
    03829       ch->bc = bc;
    03830       ch->l3id=bc->l3_id;
    03831       ch->addr=bc->addr;
    03832       ch->orginator = ORG_MISDN;
    03833
    03834       chan=misdn_new(ch, AST_STATE_RESERVED,bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
    03835
    03836       if (!chan) {
    03837          misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
    03838          ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n");
    03839          return 0;
    03840       }
    03841
    03842       ch->ast = chan;
    03843
    03844       read_config(ch, ORG_MISDN);
    03845
    03846       export_ch(chan, bc, ch);
    03847
    03848       ch->ast->rings=1;
    03849       ast_setstate(ch->ast, AST_STATE_RINGING);
    03850
    03851       int pres,screen;
    03852
    03853       switch (bc->pres) {
    03854          case 1:
    03855             pres=AST_PRES_RESTRICTED; chan_misdn_log(2,bc->port," --> PRES: Restricted (1)\n");
    03856             break;
    03857          case 2:
    03858             pres=AST_PRES_UNAVAILABLE; chan_misdn_log(2,bc->port," --> PRES: Restricted (2)\n");
    03859             break;
    03860          default:
    03861             pres=AST_PRES_ALLOWED; chan_misdn_log(2,bc->port," --> PRES: Restricted (%d)\n", bc->pres);
    03862       }
    03863
    03864       switch (bc->screen) {
    03865          case 0:
    03866             screen=AST_PRES_USER_NUMBER_UNSCREENED;  chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (0)\n");
    03867             break;
    03868          case 1:
    03869             screen=AST_PRES_USER_NUMBER_PASSED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: Passed screen (1)\n");
    03870             break;
    03871          case 2:
    03872             screen=AST_PRES_USER_NUMBER_FAILED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: failed screen (2)\n");
    03873             break;
    03874          case 3:
    03875             screen=AST_PRES_NETWORK_NUMBER; chan_misdn_log(2,bc->port," --> SCREEN: Network Number (3)\n");
    03876             break;
    03877          default:
    03878             screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (%d)\n",bc->screen);
    03879       }
    03880
    03881       chan->cid.cid_pres=pres+screen;
    03882
    03883       pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
    03884       chan->transfercapability=bc->capability;
    03885
    03886       switch (bc->capability) {
    03887          case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
    03888             pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
    03889             break;
    03890          default:
    03891             pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH");
    03892       }
    03893
    03894       /** queue new chan **/
    03895       cl_queue_chan(&cl_te, ch) ;
    03896
    03897       if (!strstr(ch->allowed_bearers,"all")) {
    03898          int i;
    03899          for (i=0; i< sizeof(allowed_bearers_array)/sizeof(struct allowed_bearers); i++) {
    03900             if (allowed_bearers_array[i].cap == bc->capability) {
    03901                if (  !strstr( ch->allowed_bearers, allowed_bearers_array[i].name)) {
    03902                   chan_misdn_log(0,bc->port,"Bearer Not allowed\b");
    03903                   bc->out_cause=88;
    03904
    03905                   ch->state=MISDN_EXTCANTMATCH;
    03906                   misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
    03907                   return RESPONSE_OK;
    03908                }
    03909             }
    03910
    03911          }
    03912       }
    03913
    03914       /* Check for Pickup Request first */
    03915       if (!strcmp(chan->exten, ast_pickup_ext())) {
    03916          if (!ch->noautorespond_on_setup) {
    03917             int ret;/** Sending SETUP_ACK**/
    03918             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
    03919          } else {
    03920             ch->state = MISDN_INCOMING_SETUP;
    03921          }
    03922          if (ast_pickup_call(chan)) {
    03923             hangup_chan(ch);
    03924          } else {
    03925             ch->state = MISDN_CALLING_ACKNOWLEDGE;
    03926             ast_setstate(chan, AST_STATE_DOWN);
    03927             hangup_chan(ch);
    03928             ch->ast=NULL;
    03929             break;
    03930          }
    03931       }
    03932
    03933       /*
    03934          added support for s extension hope it will help those poor cretains
    03935          which haven't overlap dial.
    03936          */
    03937       int ai;
    03938       misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
    03939       if ( ai ) {
    03940          do_immediate_setup(bc, ch , chan);
    03941          break;
    03942       }
    03943
    03944       /* check if we should jump into s when we have no dad */
    03945       int im;
    03946       misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
    03947       if ( im && ast_strlen_zero(bc->dad) ) {
    03948          do_immediate_setup(bc, ch , chan);
    03949          break;
    03950       }
    03951
    03952       chan_misdn_log(5,bc->port,"CONTEXT:%s\n",ch->context);
    03953       if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
    03954          if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
    03955             ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n",bc->port);
    03956             strcpy(ch->ast->exten, "i");
    03957             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
    03958             ch->state=MISDN_DIALING;
    03959             start_pbx(ch, bc, chan);
    03960             break;
    03961          }
    03962
    03963          ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d)."
    03964                "maybe you want to add an 'i' extension to catch this case.\n",
    03965                bc->port);
    03966          if (bc->nt)
    03967             hanguptone_indicate(ch);
    03968
    03969          ch->state=MISDN_EXTCANTMATCH;
    03970          bc->out_cause=1;
    03971
    03972          if (bc->nt)
    03973             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
    03974          else
    03975             misdn_lib_send_event(bc, EVENT_RELEASE );
    03976
    03977          break;
    03978       }
    03979
    03980       /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely
    03981        * jump into the dialplan, when the dialed extension does not exist, the 's' extension
    03982        * will be used by Asterisk automatically. */
    03983       if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
    03984          if (!ch->noautorespond_on_setup) {
    03985             ch->state=MISDN_DIALING;
    03986             misdn_lib_send_event(bc, EVENT_PROCEEDING );
    03987          } else {
    03988             ch->state = MISDN_INCOMING_SETUP;
    03989          }
    03990          start_pbx(ch, bc, chan);
    03991          break;
    03992       }
    03993
    03994       /*
    03995        * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more
    03996        * Infos with a Interdigit Timeout.
    03997        * */
    03998       if (ch->overlap_dial) {
    03999          ast_mutex_lock(&ch->overlap_tv_lock);
    04000          ch->overlap_tv = ast_tvnow();
    04001          ast_mutex_unlock(&ch->overlap_tv_lock);
    04002
    04003          if (ch->overlap_dial_task == -1)
    04004             ch->overlap_dial_task =
    04005                misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
    04006
    04007          wait_for_digits(ch, bc, chan);
    04008          break;
    04009       }
    04010
    04011       /* If the extension does not exist and we're not TE_PTMP we wait for more digis
    04012        * without interdigit timeout.
    04013        * */
    04014       if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
    04015          wait_for_digits(ch, bc, chan);
    04016          break;
    04017       }
    04018
    04019       /*
    04020        * If the extension exists let's just jump into it.
    04021        * */
    04022       if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
    04023          if (bc->need_more_infos)
    04024             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
    04025          else
    04026             misdn_lib_send_event(bc, EVENT_PROCEEDING);
    04027
    04028          ch->state=MISDN_DIALING;
    04029          start_pbx(ch, bc, chan);
    04030          break;
    04031       }
    04032
    04033    }
    04034    break;
    04035
    04036    case EVENT_SETUP_ACKNOWLEDGE:
    04037    {
    04038       ch->state = MISDN_CALLING_ACKNOWLEDGE;
    04039       if (!ast_strlen_zero(bc->infos_pending)) {
    04040          /* TX Pending Infos */
    04041
    04042          {
    04043             int l = sizeof(bc->dad);
    04044             strncat(bc->dad,bc->infos_pending, l - strlen(bc->dad));
    04045             bc->dad[l-1] = 0;
    04046          }
    04047
    04048          if (!ch->ast) break;
    04049          {
    04050             int l = sizeof(ch->ast->exten);
    04051             strncpy(ch->ast->exten, bc->dad, l);
    04052             ch->ast->exten[l-1] = 0;
    04053          }
    04054          {
    04055             int l = sizeof(bc->info_dad);
    04056             strncpy(bc->info_dad, bc->infos_pending, l);
    04057             bc->info_dad[l-1] = 0;
    04058          }
    04059          strncpy(bc->infos_pending,"", 1);
    04060
    04061          misdn_lib_send_event(bc, EVENT_INFORMATION);
    04062       }
    04063    }
    04064    break;
    04065    case EVENT_PROCEEDING:
    04066    {
    04067       if ( misdn_cap_is_speech(bc->capability) &&
    04068            misdn_inband_avail(bc) ) {
    04069          start_bc_tones(ch);
    04070       }
    04071
    04072       ch->state = MISDN_PROCEEDING;
    04073
    04074       if (!ch->ast) break;
    04075
    04076       ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
    04077    }
    04078    break;
    04079    case EVENT_PROGRESS:
    04080
    04081
    04082       if (!bc->nt ) {
    04083          if ( misdn_cap_is_speech(bc->capability) &&
    04084               misdn_inband_avail(bc)
    04085             ) {
    04086             start_bc_tones(ch);
    04087          }
    04088
    04089          ch->state=MISDN_PROGRESS;
    04090
    04091          if (!ch->ast) break;
    04092          ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
    04093       }
    04094       break;
    04095
    04096
    04097    case EVENT_ALERTING:
    04098    {
    04099       ch->state = MISDN_ALERTING;
    04100
    04101       if (!ch->ast) break;
    04102
    04103       ast_queue_control(ch->ast, AST_CONTROL_RINGING);
    04104       ast_setstate(ch->ast, AST_STATE_RINGING);
    04105
    04106       cb_log(7,bc->port," --> Set State Ringing\n");
    04107
    04108       if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
    04109          cb_log(1,bc->port,"Starting Tones, we have inband Data\n");
    04110          start_bc_tones(ch);
    04111       } else {
    04112          cb_log(3,bc->port," --> We have no inband Data, the other end must create ringing\n");
    04113          if (ch->far_alerting) {
    04114             cb_log(1,bc->port," --> The other end can not do ringing eh ?.. we must do all ourself..");
    04115             start_bc_tones(ch);
    04116             /*tone_indicate(ch, TONE_FAR_ALERTING);*/
    04117          }
    04118       }
    04119    }
    04120    break;
    04121    case EVENT_CONNECT:
    04122    {
    04123       /*we answer when we've got our very new L3 ID from the NT stack */
    04124       misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
    04125
    04126       if (!ch->ast) break;
    04127
    04128       struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
    04129       stop_indicate(ch);
    04130
    04131       if (bridged && !strcasecmp(bridged->tech->type,"mISDN")) {
    04132          struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
    04133
    04134          chan_misdn_log(1,bc->port," --> copying cpndialplan:%d and cad:%s to the A-Channel\n",bc->cpnnumplan,bc->cad);
    04135          if (bridged_ch) {
    04136             bridged_ch->bc->cpnnumplan=bc->cpnnumplan;
    04137             ast_copy_string(bridged_ch->bc->cad,bc->cad,sizeof(bc->cad));
    04138          }
    04139       }
    04140    }
    04141
    04142    /* notice that we don't break here!*/
    04143    case EVENT_CONNECT_ACKNOWLEDGE:
    04144    {
    04145       ch->l3id=bc->l3_id;
    04146       ch->addr=bc->addr;
    04147
    04148       start_bc_tones(ch);
    04149
    04150       ch->state = MISDN_CONNECTED;
    04151
    04152       if (!ch->ast) break;
    04153
    04154       ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
    04155    }
    04156    break;
    04157    case EVENT_DISCONNECT:
    04158    /*we might not have an ch->ast ptr here anymore*/
    04159    if (ch) {
    04160       struct chan_list *holded_ch=find_holded(cl_te, bc);
    04161
    04162       chan_misdn_log(3,bc->port," --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->orginator, bc->nt, misdn_inband_avail(bc), ch->state);
    04163       if ( ch->orginator==ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
    04164          /* If there's inband information available (e.g. a
    04165             recorded message saying what was wrong with the
    04166             dialled number, or perhaps even giving an
    04167             alternative number, then play it instead of
    04168             immediately releasing the call */
    04169          chan_misdn_log(1,bc->port, " --> Inband Info Avail, not sending RELEASE\n");
    04170
    04171          ch->state=MISDN_DISCONNECTED;
    04172          start_bc_tones(ch);
    04173
    04174          if (ch->ast) {
    04175             ch->ast->hangupcause=bc->cause;
    04176             if (bc->cause == 17)
    04177                ast_queue_control(ch->ast, AST_CONTROL_BUSY);
    04178          }
    04179          ch->need_busy=0;
    04180          break;
    04181       }
    04182
    04183       /*Check for holded channel, to implement transfer*/
    04184       if (  holded_ch &&
    04185          holded_ch != ch &&
    04186          ch->ast &&
    04187          ch->state == MISDN_CONNECTED  ) {
    04188          cb_log(1,bc->port," --> found holded ch\n");
    04189          misdn_transfer_bc(ch, holded_ch) ;
    04190       }
    04191
    04192       bc->need_disconnect=0;
    04193
    04194       stop_bc_tones(ch);
    04195       hangup_chan(ch);
    04196    } else {
    04197       ch=find_holded_l3(cl_te, bc->l3_id,1);
    04198       if (ch) {
    04199          hangup_chan(ch);
    04200       }
    04201    }
    04202    bc->out_cause=-1;
    04203    if (bc->need_release) misdn_lib_send_event(bc,EVENT_RELEASE);
    04204    break;
    04205
    04206    case EVENT_RELEASE:
    04207       {
    04208          bc->need_disconnect=0;
    04209          bc->need_release=0;
    04210
    04211          hangup_chan(ch);
    04212          release_chan(bc);
    04213
    04214          if (bc->need_release_complete)
    04215             misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
    04216       }
    04217       break;
    04218    case EVENT_RELEASE_COMPLETE:
    04219    {
    04220       bc->need_disconnect=0;
    04221       bc->need_release=0;
    04222       bc->need_release_complete=0;
    04223
    04224       stop_bc_tones(ch);
    04225       hangup_chan(ch);
    04226
    04227       if(ch)
    04228          ch->state=MISDN_CLEANING;
    04229
    04230       release_chan(bc);
    04231    }
    04232    break;
    04233    case EVENT_BCHAN_ERROR:
    04234    case EVENT_CLEANUP:
    04235    {
    04236       stop_bc_tones(ch);
    04237
    04238       switch(ch->state) {
    04239          case MISDN_CALLING:
    04240             bc->cause=27; /* Destination out of order */
    04241          break;
    04242          default:
    04243          break;
    04244       }
    04245
    04246       hangup_chan(ch);
    04247       release_chan(bc);
    04248    }
    04249    break;
    04250
    04251    case EVENT_TONE_GENERATE:
    04252    {
    04253       int tone_len=bc->tone_cnt;
    04254       struct ast_channel *ast=ch->ast;
    04255       void *tmp;
    04256       int res;
    04257       int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
    04258
    04259       chan_misdn_log(9,bc->port,"TONE_GEN: len:%d\n");
    04260
    04261       if (!ast) break;
    04262
    04263       if (!ast->generator) break;
    04264
    04265
    04266
    04267       tmp = ast->generatordata;
    04268       ast->generatordata = NULL;
    04269       generate = ast->generator->generate;
    04270
    04271       if (tone_len <0 || tone_len > 512 ) {
    04272          ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n",tone_len);
    04273          tone_len=128;
    04274       }
    04275
    04276       res = generate(ast, tmp, tone_len, tone_len);
    04277       ast->generatordata = tmp;
    04278
    04279       if (res) {
    04280          ast_log(LOG_WARNING, "Auto-deactivating generator\n");
    04281          ast_deactivate_generator(ast);
    04282       } else {
    04283          bc->tone_cnt=0;
    04284       }
    04285    }
    04286    break;
    04287
    04288    case EVENT_BCHAN_DATA:
    04289    {
    04290       if ( !misdn_cap_is_speech(ch->bc->capability) ) {
    04291          struct ast_frame frame;
    04292          /*In Data Modes we queue frames*/
    04293          frame.frametype  = AST_FRAME_VOICE; /*we have no data frames yet*/
    04294          frame.subclass = AST_FORMAT_ALAW;
    04295          frame.datalen = bc->bframe_len;
    04296          frame.samples = bc->bframe_len ;
    04297          frame.mallocd =0 ;
    04298          frame.offset= 0 ;
    04299          frame.delivery= ast_tv(0,0) ;
    04300          frame.src = NULL;
    04301          frame.data = bc->bframe ;
    04302
    04303          if (ch->ast)
    04304             ast_queue_frame(ch->ast,&frame);
    04305       } else {
    04306          fd_set wrfs;
    04307          struct timeval tv;
    04308          tv.tv_sec=0;
    04309          tv.tv_usec=0;
    04310
    04311
    04312          FD_ZERO(&wrfs);
    04313          FD_SET(ch->pipe[1],&wrfs);
    04314
    04315          int t=select(FD_SETSIZE,NULL,&wrfs,NULL,&tv);
    04316
    04317          if (!t) {
    04318             chan_misdn_log(9, bc->port, "Select Timed out\n");
    04319             break;
    04320          }
    04321
    04322          if (t<0) {
    04323             chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n",strerror(errno));
    04324             break;
    04325          }
    04326
    04327          if (FD_ISSET(ch->pipe[1],&wrfs)) {
    04328             chan_misdn_log(9, bc->port, "writing %d bytes 2 asterisk\n",bc->bframe_len);
    04329             int ret=write(ch->pipe[1], bc->bframe, bc->bframe_len);
    04330
    04331             if (ret<=0) {
    04332                chan_misdn_log(-1, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n",strerror(errno));
    04333
    04334                stop_bc_tones(ch);
    04335                hangup_chan(ch);
    04336                release_chan(bc);
    04337             }
    04338          } else {
    04339             chan_misdn_log(1, bc->port, "Wripe Pipe full!\n");
    04340          }
    04341       }
    04342    }
    04343    break;
    04344    case EVENT_TIMEOUT:
    04345       {
    04346       if (ch && bc)
    04347          chan_misdn_log(1,bc->port,"--> state: %s\n",misdn_get_ch_state(ch));
    04348
    04349       switch (ch->state) {
    04350          case MISDN_DIALING:
    04351          case MISDN_PROGRESS:
    04352             if (bc->nt && !ch->nttimeout) break;
    04353
    04354          case MISDN_CALLING:
    04355          case MISDN_ALERTING:
    04356          case MISDN_PROCEEDING:
    04357          case MISDN_CALLING_ACKNOWLEDGE:
    04358             if (bc->nt) {
    04359                bc->progress_indicator=8;
    04360                hanguptone_indicate(ch);
    04361             }
    04362
    04363             bc->out_cause=1;
    04364             misdn_lib_send_event(bc,EVENT_DISCONNECT);
    04365          break;
    04366
    04367          case MISDN_WAITING4DIGS:
    04368             if (bc->nt) {
    04369                bc->progress_indicator=8;
    04370                bc->out_cause=1;
    04371                hanguptone_indicate(ch);
    04372                misdn_lib_send_event(bc,EVENT_DISCONNECT);
    04373             } else {
    04374                bc->out_cause=16;
    04375                misdn_lib_send_event(bc,EVENT_RELEASE);
    04376             }
    04377
    04378          break;
    04379
    04380
    04381          case MISDN_CLEANING:
    04382             chan_misdn_log(1,bc->port," --> in state cleaning .. so ingoring, the stack should clean it for us\n");
    04383          break;
    04384
    04385          default:
    04386             misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
    04387          }
    04388       }
    04389       break;
    04390
    04391
    04392    /***************************/
    04393    /** Suplementary Services **/
    04394    /***************************/
    04395    case EVENT_RETRIEVE:
    04396    {
    04397       if (!ch) {
    04398          chan_misdn_log(4, bc->port, " --> no CH, searching in holded");
    04399          ch=find_holded_l3(cl_te, bc->l3_id,1);
    04400       }
    04401
    04402       if (!ch) {
    04403          ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
    04404          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
    04405          break;
    04406       }
    04407
    04408       /*remember the channel again*/
    04409       ch->bc=bc;
    04410       ch->state = MISDN_CONNECTED;
    04411
    04412       ch->hold_info.port=0;
    04413       ch->hold_info.channel=0;
    04414
    04415       struct ast_channel *hold_ast=AST_BRIDGED_P(ch->ast);
    04416
    04417       if (hold_ast) {
    04418          ast_moh_stop(hold_ast);
    04419       }
    04420
    04421       if ( misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0)
    04422          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
    04423    }
    04424    break;
    04425
    04426    case EVENT_HOLD:
    04427    {
    04428       int hold_allowed;
    04429       misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
    04430
    04431       if (!hold_allowed) {
    04432
    04433          chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
    04434          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
    04435          break;
    04436       }
    04437
    04438       struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
    04439
    04440       if (bridged) {
    04441          chan_misdn_log(2,bc->port,"Bridge Partner is of type: %s\n",bridged->tech->type);
    04442          ch->state = MISDN_HOLDED;
    04443          ch->l3id = bc->l3_id;
    04444
    04445          misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
    04446
    04447          ast_moh_start(bridged, NULL);
    04448
    04449          /*forget the channel now*/
    04450          ch->bc=NULL;
    04451          ch->hold_info.port=bc->port;
    04452          ch->hold_info.channel=bc->channel;
    04453
    04454       } else {
    04455          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
    04456          chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
    04457       }
    04458    }
    04459    break;
    04460
    04461    case EVENT_FACILITY:
    04462       print_facility(bc);
    04463
    04464       switch (bc->fac_type) {
    04465       case FACILITY_CALLDEFLECT:
    04466       {
    04467          struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
    04468          struct chan_list *ch;
    04469
    04470          if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
    04471             ch=MISDN_ASTERISK_TECH_PVT(bridged);
    04472             /*ch->state=MISDN_FACILITY_DEFLECTED;*/
    04473             if (ch->bc) {
    04474                /* todo */
    04475             }
    04476
    04477          }
    04478
    04479       }
    04480
    04481       break;
    04482       default:
    04483          chan_misdn_log(1, bc->port," --> not yet handled\n");
    04484       }
    04485
    04486       break;
    04487
    04488    case EVENT_RESTART:
    04489
    04490       if (!bc->dummy) {
    04491          stop_bc_tones(ch);
    04492          release_chan(bc);
    04493       }
    04494
    04495       break;
    04496
    04497    default:
    04498       chan_misdn_log(1,0, "Got Unknown Event\n");
    04499       break;
    04500    }
    04501
    04502    return RESPONSE_OK;
    04503 }
    04504
    04505 /** TE STUFF END **/
    04506
    04507 /******************************************
    04508  *
    04509  *   Asterisk Channel Endpoint END
    04510  *
    04511  *
    04512  *******************************************/
    04513
    04514
    04515
    04516 int load_module(void)
    04517 {
    04518    int i;
    04519
    04520    char ports[256]="";
    04521
    04522    max_ports=misdn_lib_maxports_get();
    04523
    04524    if (max_ports<=0) {
    04525       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
    04526       return 0;
    04527    }
    04528
    04529    if (misdn_cfg_init(max_ports)<0) {
    04530       ast_log(LOG_ERROR, "Unable to initialize mISDN Config System\n");
    04531       return 0;
    04532    }
    04533
    04534    g_config_initialized=1;
    04535
    04536    misdn_debug = (int *)malloc(sizeof(int) * (max_ports+1));
    04537    misdn_cfg_get( 0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
    04538    for (i = 1; i <= max_ports; i++)
    04539       misdn_debug[i] = misdn_debug[0];
    04540    misdn_debug_only = (int *)calloc(max_ports + 1, sizeof(int));
    04541
    04542
    04543    {
    04544       char tempbuf[BUFFERSIZE+1];
    04545       misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
    04546       if (strlen(tempbuf))
    04547          tracing = 1;
    04548    }
    04549
    04550    ast_mutex_init(&cl_te_lock);
    04551    ast_mutex_init(&release_lock);
    04552
    04553    misdn_cfg_update_ptp();
    04554    misdn_cfg_get_ports_string(ports);
    04555
    04556    if (strlen(ports))
    04557       chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
    04558
    04559    {
    04560       struct misdn_lib_iface iface = {
    04561          .cb_event = cb_events,
    04562          .cb_log = chan_misdn_log,
    04563          .cb_jb_empty = chan_misdn_jb_empty,
    04564       };
    04565       if (misdn_lib_init(ports, &iface, NULL))
    04566          chan_misdn_log(0, 0, "No te ports initialized\n");
    04567
    04568       int ntflags=0;
    04569       char ntfile[BUFFERSIZE+1];
    04570
    04571       misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(int));
    04572       misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFILE, &ntfile, BUFFERSIZE);
    04573
    04574       misdn_lib_nt_debug_init(ntflags,ntfile);
    04575
    04576    }
    04577
    04578
    04579    {
    04580       if (ast_channel_register(&misdn_tech)) {
    04581          ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
    04582          unload_module();
    04583          return -1;
    04584       }
    04585    }
    04586
    04587    ast_cli_register(&cli_send_display);
    04588    ast_cli_register(&cli_send_cd);
    04589    ast_cli_register(&cli_send_restart);
    04590    ast_cli_register(&cli_send_digit);
    04591    ast_cli_register(&cli_toggle_echocancel);
    04592    ast_cli_register(&cli_set_tics);
    04593
    04594    ast_cli_register(&cli_show_cls);
    04595    ast_cli_register(&cli_show_cl);
    04596    ast_cli_register(&cli_show_config);
    04597    ast_cli_register(&cli_show_port);
    04598    ast_cli_register(&cli_show_stacks);
    04599
    04600    ast_cli_register(&cli_port_block);
    04601    ast_cli_register(&cli_port_unblock);
    04602    ast_cli_register(&cli_restart_port);
    04603    ast_cli_register(&cli_restart_pid);
    04604    ast_cli_register(&cli_port_up);
    04605    ast_cli_register(&cli_port_down);
    04606    ast_cli_register(&cli_set_debug);
    04607    ast_cli_register(&cli_set_crypt_debug);
    04608    ast_cli_register(&cli_reload);
    04609
    04610
    04611    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
    04612              "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
    04613              "Sets mISDN opts. and optargs\n"
    04614              "\n"
    04615              "The available options are:\n"
    04616              "    d - Send display text on called phone, text is the optparam\n"
    04617              "    n - don't detect dtmf tones on called channel\n"
    04618              "    h - make digital outgoing call\n"
    04619              "    c - make crypted outgoing call, param is keyindex\n"
    04620              "    e - perform echo cancelation on this channel,\n"
    04621              "        takes taps as arguments (32,64,128,256)\n"
    04622              "    s - send Non Inband DTMF as inband\n"
    04623              "   vr - rxgain control\n"
    04624              "   vt - txgain control\n"
    04625       );
    04626
    04627
    04628    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
    04629              "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
    04630              "Sends the Facility Message FACILITY_TYPE with \n"
    04631              "the given Arguments to the current ISDN Channel\n"
    04632              "Supported Facilities are:\n"
    04633              "\n"
    04634              "type=calldeflect args=Nr where to deflect\n"
    04635       );
    04636
    04637
    04638    ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
    04639              "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
    04640              "Checks if the L2 and L1 are up on either the given <port> or\n"
    04641              "on the ports in the group with <groupname>\n"
    04642              "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
    04643              "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
    04644              "\n"
    04645              "This application, ensures the L1/L2 state of the Ports in a group\n"
    04646              "it is intended to make the pmp_l1_check option redundant and to\n"
    04647              "fix a buggy switch config from your provider\n"
    04648              "\n"
    04649              "a sample dialplan would look like:\n\n"
    04650              "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
    04651              "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
    04652              "\n"
    04653       );
    04654
    04655
    04656    misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
    04657
    04658    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
    04659
    04660    return 0;
    04661 }
    04662
    04663
    04664
    04665 int unload_module(void)
    04666 {
    04667    /* First, take us out of the channel loop */
    04668    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
    04669
    04670    misdn_tasks_destroy();
    04671
    04672    if (!g_config_initialized) return 0;
    04673
    04674    ast_cli_unregister(&cli_send_display);
    04675
    04676    ast_cli_unregister(&cli_send_cd);
    04677    ast_cli_unregister(&cli_send_restart);
    04678
    04679    ast_cli_unregister(&cli_send_digit);
    04680    ast_cli_unregister(&cli_toggle_echocancel);
    04681    ast_cli_unregister(&cli_set_tics);
    04682
    04683    ast_cli_unregister(&cli_show_cls);
    04684    ast_cli_unregister(&cli_show_cl);
    04685    ast_cli_unregister(&cli_show_config);
    04686    ast_cli_unregister(&cli_show_port);
    04687    ast_cli_unregister(&cli_show_stacks);
    04688    ast_cli_unregister(&cli_port_block);
    04689    ast_cli_unregister(&cli_port_unblock);
    04690    ast_cli_unregister(&cli_restart_port);
    04691    ast_cli_unregister(&cli_restart_pid);
    04692    ast_cli_unregister(&cli_port_up);
    04693    ast_cli_unregister(&cli_port_down);
    04694    ast_cli_unregister(&cli_set_debug);
    04695    ast_cli_unregister(&cli_set_crypt_debug);
    04696    ast_cli_unregister(&cli_reload);
    04697    /* ast_unregister_application("misdn_crypt"); */
    04698    ast_unregister_application("misdn_set_opt");
    04699    ast_unregister_application("misdn_facility");
    04700    ast_unregister_application("misdn_check_l2l1");
    04701
    04702    ast_channel_unregister(&misdn_tech);
    04703
    04704
    04705    free_robin_list();
    04706    misdn_cfg_destroy();
    04707    misdn_lib_destroy();
    04708
    04709    if (misdn_debug)
    04710       free(misdn_debug);
    04711    if (misdn_debug_only)
    04712       free(misdn_debug_only);
    04713
    04714    return 0;
    04715 }
    04716
    04717 int reload(void)
    04718 {
    04719    reload_config();
    04720
    04721    return 0;
    04722 }
    04723
    04724 int usecount(void)
    04725 {
    04726    int res;
    04727    ast_mutex_lock(&usecnt_lock);
    04728    res = usecnt;
    04729    ast_mutex_unlock(&usecnt_lock);
    04730    return res;
    04731 }
    04732
    04733 char *description(void)
    04734 {
    04735    return desc;
    04736 }
    04737
    04738 char *key(void)
    04739 {
    04740    return ASTERISK_GPL_KEY;
    04741 }
    04742
    04743
    04744
    04745
    04746 /*** SOME APPS ;)***/
    04747
    04748 static int misdn_facility_exec(struct ast_channel *chan, void *data)
    04749 {
    04750    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
    04751    char *tok, *tokb;
    04752
    04753    chan_misdn_log(0,0,"TYPE: %s\n",chan->tech->type);
    04754
    04755    if (strcasecmp(chan->tech->type,"mISDN")) {
    04756       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
    04757       return -1;
    04758    }
    04759
    04760    if (ast_strlen_zero((char *)data)) {
    04761       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
    04762       return -1;
    04763    }
    04764
    04765    tok=strtok_r((char*)data,"|", &tokb) ;
    04766
    04767    if (!tok) {
    04768       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
    04769       return -1;
    04770    }
    04771
    04772    if (!strcasecmp(tok,"calldeflect")) {
    04773       tok=strtok_r(NULL,"|", &tokb) ;
    04774
    04775       if (!tok) {
    04776          ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
    04777       }
    04778
    04779       misdn_lib_send_facility(ch->bc, FACILITY_CALLDEFLECT, tok);
    04780
    04781    } else {
    04782       chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n",tok);
    04783    }
    04784
    04785    return 0;
    04786
    04787 }
    04788
    04789 static int misdn_check_l2l1(struct ast_channel *chan, void *data)
    04790 {
    04791    AST_DECLARE_APP_ARGS(args,
    04792          AST_APP_ARG(grouppar);
    04793          AST_APP_ARG(timeout);
    04794    );
    04795
    04796    if (ast_strlen_zero((char *)data)) {
    04797       ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
    04798       return -1;
    04799    }
    04800
    04801    AST_STANDARD_APP_ARGS(args, data);
    04802
    04803    if (args.argc != 2) {
    04804       ast_log(LOG_WARNING, "Wrong argument count\n");
    04805       return 0;
    04806    }
    04807
    04808    /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
    04809    char group[BUFFERSIZE+1];
    04810    char *port_str;
    04811
    04812    int port=0;
    04813    int timeout=atoi(args.timeout);
    04814    int dowait=0;
    04815
    04816    port_str=args.grouppar;
    04817
    04818    int port_up;
    04819    if (port_str[0]=='g' && port_str[1]==':' ) {
    04820       /* We make a group call lets checkout which ports are in my group */
    04821       port_str += 2;
    04822       strncpy(group, port_str, BUFFERSIZE);
    04823       group[BUFFERSIZE-1] = 0;
    04824       chan_misdn_log(2, 0, "Checking Ports in group: %s\n",group);
    04825
    04826       for ( port = misdn_cfg_get_next_port(port);
    04827          port > 0;
    04828          port = misdn_cfg_get_next_port(port)) {
    04829
    04830          chan_misdn_log(2,0,"trying port %d\n",port);
    04831
    04832          char cfg_group[BUFFERSIZE+1];
    04833          misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
    04834
    04835          if (!strcasecmp(cfg_group, group)) {
    04836             port_up = misdn_lib_port_up(port, 1);
    04837
    04838             if (!port_up) {
    04839                chan_misdn_log(2, 0, " --> port '%d'\n", port);
    04840                misdn_lib_get_port_up(port);
    04841                dowait=1;
    04842             }
    04843          }
    04844       }
    04845
    04846    } else {
    04847       port = atoi(port_str);
    04848       chan_misdn_log(2, 0, "Checking Port: %d\n",port);
    04849       port_up = misdn_lib_port_up(port, 1);
    04850       if (!port_up) {
    04851          misdn_lib_get_port_up(port);
    04852          dowait=1;
    04853       }
    04854
    04855    }
    04856
    04857    if (dowait) {
    04858       chan_misdn_log(2, 0, "Waiting for '%d' seconds\n",timeout);
    04859       sleep(timeout);
    04860    }
    04861
    04862    return 0;
    04863 }
    04864
    04865 static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
    04866 {
    04867    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
    04868    char *tok,*tokb;
    04869    int  keyidx=0;
    04870    int rxgain=0;
    04871    int txgain=0;
    04872    int change_jitter=0;
    04873
    04874    if (strcasecmp(chan->tech->type,"mISDN")) {
    04875       ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
    04876       return -1;
    04877    }
    04878
    04879    if (ast_strlen_zero((char *)data)) {
    04880       ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
    04881       return -1;
    04882    }
    04883
    04884    for (tok=strtok_r((char*)data, ":",&tokb);
    04885         tok;
    04886         tok=strtok_r(NULL,":",&tokb) ) {
    04887       int neglect=0;
    04888
    04889       if (tok[0] == '!' ) {
    04890          neglect=1;
    04891          tok++;
    04892       }
    04893
    04894       switch(tok[0]) {
    04895
    04896       case 'd' :
    04897          ast_copy_string(ch->bc->display,++tok,84);
    04898          chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n",ch->bc->display);
    04899          break;
    04900
    04901       case 'n':
    04902          chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
    04903          ch->bc->nodsp=1;
    04904          break;
    04905
    04906       case 'j':
    04907          chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
    04908          tok++;
    04909          change_jitter=1;
    04910
    04911          switch ( tok[0] ) {
    04912          case 'b' :
    04913             ch->jb_len=atoi(++tok);
    04914             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n",ch->jb_len);
    04915             break;
    04916          case 't' :
    04917             ch->jb_upper_threshold=atoi(++tok);
    04918             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n",ch->jb_upper_threshold);
    04919             break;
    04920
    04921          case 'n':
    04922             ch->bc->nojitter=1;
    04923             chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
    04924             break;
    04925
    04926          default:
    04927             ch->jb_len=4000;
    04928             ch->jb_upper_threshold=0;
    04929             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n",ch->jb_len);
    04930             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n",ch->jb_upper_threshold);
    04931          }
    04932
    04933          break;
    04934
    04935       case 'v':
    04936          tok++;
    04937
    04938          switch ( tok[0] ) {
    04939          case 'r' :
    04940             rxgain=atoi(++tok);
    04941             if (rxgain<-8) rxgain=-8;
    04942             if (rxgain>8) rxgain=8;
    04943             ch->bc->rxgain=rxgain;
    04944             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",rxgain);
    04945             break;
    04946          case 't':
    04947             txgain=atoi(++tok);
    04948             if (txgain<-8) txgain=-8;
    04949             if (txgain>8) txgain=8;
    04950             ch->bc->txgain=txgain;
    04951             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",txgain);
    04952             break;
    04953          }
    04954          break;
    04955
    04956       case 'c':
    04957          keyidx=atoi(++tok);
    04958
    04959          char keys[4096];
    04960          char *key=NULL, *tmp;
    04961          int i;
    04962          misdn_cfg_get( 0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
    04963
    04964          tmp=keys;
    04965
    04966          for (i=0; i<keyidx; i++) {
    04967             key=strsep(&tmp,",");
    04968          }
    04969
    04970          if (key) {
    04971             ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
    04972          }
    04973
    04974          chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n",ch->bc->crypt_key);
    04975          break;
    04976
    04977       case 'e':
    04978          chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
    04979
    04980          if (neglect) {
    04981             chan_misdn_log(1, ch->bc->port, " --> disabled\n");
    04982 #ifdef MISDN_1_2
    04983             *ch->bc->pipeline=0;
    04984 #else
    04985             ch->bc->ec_enable=0;
    04986 #endif
    04987          } else {
    04988 #ifdef MISDN_1_2
    04989             update_pipeline_config(ch->bc);
    04990 #else
    04991             ch->bc->ec_enable=1;
    04992             ch->bc->orig=ch->orginator;
    04993             tok++;
    04994             if (*tok) {
    04995                ch->bc->ec_deftaps=atoi(tok);
    04996             }
    04997 #endif
    04998          }
    04999
    05000          break;
    05001
    05002       case 'h':
    05003          chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
    05004
    05005          if (strlen(tok) > 1 && tok[1]=='1') {
    05006             chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
    05007             if (!ch->bc->hdlc) {
    05008                ch->bc->hdlc=1;
    05009             }
    05010          }
    05011          ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
    05012          break;
    05013
    05014       case 's':
    05015          chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
    05016          ch->bc->send_dtmf=1;
    05017          break;
    05018
    05019       case 'f':
    05020          chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
    05021          ch->faxdetect=1;
    05022          break;
    05023
    05024       case 'a':
    05025          chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
    05026          ch->ast_dsp=1;
    05027          break;
    05028
    05029       case 'p':
    05030          chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n",&tok[1]);
    05031          /* CRICH: callingpres!!! */
    05032          if (strstr(tok,"allowed") ) {
    05033             ch->bc->pres=0;
    05034          } else if (strstr(tok,"not_screened")) {
    05035             ch->bc->pres=1;
    05036          }
    05037
    05038
    05039          break;
    05040
    05041
    05042       default:
    05043          break;
    05044       }
    05045    }
    05046
    05047    if (change_jitter)
    05048       config_jitterbuffer(ch);
    05049
    05050
    05051    if (ch->faxdetect || ch->ast_dsp) {
    05052
    05053       if (!ch->dsp) ch->dsp = ast_dsp_new();
    05054       if (ch->dsp) ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
    05055       if (!ch->trans) ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
    05056    }
    05057
    05058    if (ch->ast_dsp) {
    05059       chan_misdn_log(1,ch->bc->port,"SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
    05060       ch->bc->nodsp=1;
    05061       ch->bc->nojitter=1;
    05062    }
    05063
    05064    return 0;
    05065 }
    05066
    05067
    05068 int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len)
    05069 {
    05070    struct chan_list *ch=find_chan_by_bc(cl_te, bc);
    05071
    05072    if (ch && ch->jb) {
    05073       return misdn_jb_empty(ch->jb, buf, len);
    05074    }
    05075
    05076    return -1;
    05077 }
    05078
    05079
    05080
    05081 /*******************************************************/
    05082 /***************** JITTERBUFFER ************************/
    05083 /*******************************************************/
    05084
    05085
    05086 /* allocates the jb-structure and initialise the elements*/
    05087 struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
    05088 {
    05089     int i;
    05090     struct misdn_jb *jb = (struct misdn_jb*) malloc(sizeof(struct misdn_jb));
    05091     jb->size = size;
    05092     jb->upper_threshold = upper_threshold;
    05093     jb->wp = 0;
    05094     jb->rp = 0;
    05095     jb->state_full = 0;
    05096     jb->state_empty = 0;
    05097     jb->bytes_wrote = 0;
    05098     jb->samples = (char *)malloc(size*sizeof(char));
    05099
    05100     if (!jb->samples) {
    05101        chan_misdn_log(-1,0,"No free Mem for jb->samples\n");
    05102        return NULL;
    05103     }
    05104
    05105     jb->ok = (char *)malloc(size*sizeof(char));
    05106
    05107     if (!jb->ok) {
    05108        chan_misdn_log(-1,0,"No free Mem for jb->ok\n");
    05109        return NULL;
    05110     }
    05111
    05112     for(i=0; i<size; i++)
    05113    jb->ok[i]=0;
    05114
    05115     ast_mutex_init(&jb->mutexjb);
    05116
    05117     return jb;
    05118 }
    05119
    05120 /* frees the data and destroys the given jitterbuffer struct */
    05121 void misdn_jb_destroy(struct misdn_jb *jb)
    05122 {
    05123    ast_mutex_destroy(&jb->mutexjb);
    05124
    05125    free(jb->samples);
    05126    free(jb);
    05127 }
    05128
    05129 /* fills the jitterbuffer with len data returns < 0 if there was an
    05130    error (bufferoverflow). */
    05131 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
    05132 {
    05133     int i, j, rp, wp;
    05134
    05135     if (!jb || ! data) return 0;
    05136
    05137     ast_mutex_lock (&jb->mutexjb);
    05138
    05139     wp=jb->wp;
    05140     rp=jb->rp;
    05141
    05142     for(i=0; i<len; i++)
    05143     {
    05144    jb->samples[wp]=data[i];
    05145    jb->ok[wp]=1;
    05146    wp = (wp!=jb->size-1 ? wp+1 : 0);
    05147
    05148    if(wp==jb->rp)
    05149        jb->state_full=1;
    05150     }
    05151
    05152     if(wp>=rp)
    05153       jb->state_buffer=wp-rp;
    05154     else
    05155       jb->state_buffer= jb->size-rp+wp;
    05156     chan_misdn_log(9,0,"misdn_jb_fill: written:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
    05157
    05158     if(jb->state_full)
    05159     {
    05160    jb->wp=wp;
    05161
    05162    rp=wp;
    05163    for(j=0; j<jb->upper_threshold; j++)
    05164        rp = (rp!=0 ? rp-1 : jb->size-1);
    05165    jb->rp=rp;
    05166    jb->state_full=0;
    05167    jb->state_empty=1;
    05168
    05169    ast_mutex_unlock (&jb->mutexjb);
    05170
    05171    return -1;
    05172     }
    05173
    05174     if(!jb->state_empty)
    05175     {
    05176    jb->bytes_wrote+=len;
    05177    if(jb->bytes_wrote>=jb->upper_threshold)
    05178    {
    05179        jb->state_empty=1;
    05180        jb->bytes_wrote=0;
    05181    }
    05182     }
    05183     jb->wp=wp;
    05184
    05185     ast_mutex_unlock (&jb->mutexjb);
    05186
    05187     return 0;
    05188 }
    05189
    05190 /* gets len bytes out of the jitterbuffer if available, else only the
    05191 available data is returned and the return value indicates the number
    05192 of data. */
    05193 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
    05194 {
    05195     int i, wp, rp, read=0;
    05196
    05197     ast_mutex_lock (&jb->mutexjb);
    05198
    05199     rp=jb->rp;
    05200     wp=jb->wp;
    05201
    05202     if(jb->state_empty)
    05203     {
    05204    for(i=0; i<len; i++)
    05205    {
    05206        if(wp==rp)
    05207        {
    05208       jb->rp=rp;
    05209       jb->state_empty=0;
    05210
    05211       ast_mutex_unlock (&jb->mutexjb);
    05212
    05213       return read;
    05214        }
    05215        else
    05216        {
    05217       if(jb->ok[rp]==1)
    05218       {
    05219           data[i]=jb->samples[rp];
    05220           jb->ok[rp]=0;
    05221           rp=(rp!=jb->size-1 ? rp+1 : 0);
    05222           read+=1;
    05223       }
    05224        }
    05225    }
    05226
    05227    if(wp >= rp)
    05228       jb->state_buffer=wp-rp;
    05229    else
    05230       jb->state_buffer= jb->size-rp+wp;
    05231    chan_misdn_log(9,0,"misdn_jb_empty: read:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
    05232
    05233    jb->rp=rp;
    05234     }
    05235     else
    05236        chan_misdn_log(9,0,"misdn_jb_empty: Wait...requested:%d p:%x\n",len,jb);
    05237
    05238     ast_mutex_unlock (&jb->mutexjb);
    05239
    05240     return read;
    05241 }
    05242
    05243
    05244
    05245
    05246 /*******************************************************/
    05247 /*************** JITTERBUFFER  END *********************/
    05248 /*******************************************************/
    05249
    05250
    05251
    05252
    05253 void chan_misdn_log(int level, int port, char *tmpl, ...)
    05254 {
    05255    if (! ((0 <= port) && (port <= max_ports))) {
    05256       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
    05257       port=0;
    05258       level=-1;
    05259    }
    05260
    05261    va_list ap;
    05262    char buf[1024];
    05263    char port_buf[8];
    05264    sprintf(port_buf,"P[%2d] ",port);
    05265
    05266    va_start(ap, tmpl);
    05267    vsnprintf( buf, 1023, tmpl, ap );
    05268    va_end(ap);
    05269
    05270    if (level == -1)
    05271       ast_log(LOG_WARNING, buf);
    05272
    05273    else if (misdn_debug_only[port] ?
    05274          (level==1 && misdn_debug[port]) || (level==misdn_debug[port])
    05275        : level <= misdn_debug[port]) {
    05276
    05277       ast_console_puts(port_buf);
    05278       ast_console_puts(buf);
    05279    }
    05280
    05281    if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
    05282       time_t tm = time(NULL);
    05283       char *tmp=ctime(&tm),*p;
    05284
    05285       FILE *fp= fopen(global_tracefile, "a+");
    05286
    05287       p=strchr(tmp,'\n');
    05288       if (p) *p=':';
    05289
    05290       if (!fp) {
    05291          ast_console_puts("Error opening Tracefile: [ ");
    05292          ast_console_puts(global_tracefile);
    05293          ast_console_puts(" ] ");
    05294
    05295          ast_console_puts(strerror(errno));
    05296          ast_console_puts("\n");
    05297          return ;
    05298       }
    05299
    05300       fputs(tmp,fp);
    05301       fputs(" ", fp);
    05302       fputs(port_buf,fp);
    05303       fputs(" ", fp);
    05304       fputs(buf, fp);
    05305
    05306       fclose(fp);
    05307    }
    05308 }
    05309
    05310