Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:50 2009

## Asterisk developer's documentation

# chan_h323.c

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (C) 1999 - 2005
    00005  *
    00006  * OpenH323 Channel Driver for ASTERISK PBX.
    00007  *       By Jeremy McNamara
    00008  *                      For The NuFone Network
    00009  *
    00010  * chan_h323 has been derived from code created by
    00011  *               Michael Manousos and Mark Spencer
    00012  *
    00013  * See http://www.asterisk.org for more information about
    00014  * the Asterisk project. Please do not directly contact
    00015  * any of the maintainers of this project for assistance;
    00016  * the project provides a web site, mailing lists and IRC
    00017  * channels for your use.
    00018  *
    00019  * This program is free software, distributed under the terms of
    00020  * the GNU General Public License Version 2. See the LICENSE file
    00021  * at the top of the source tree.
    00022  */
    00023
    00024 /*! \file
    00025  *
    00026  * \brief This file is part of the chan_h323 driver for Asterisk
    00027  *
    00028  * \par See also
    00029  * \arg Config_h323
    00030  *
    00031  * \ingroup channel_drivers
    00032  */
    00033
    00034 #include <sys/socket.h>
    00035 #include <sys/signal.h>
    00036 #include <sys/param.h>
    00037 #if defined(BSD)
    00038 #ifndef IPTOS_MINCOST
    00039 #define IPTOS_MINCOST 0x02
    00040 #endif
    00041 #endif
    00042 #include <arpa/inet.h>
    00043 #include <net/if.h>
    00044 #include <netinet/in.h>
    00045 #include <netinet/in_systm.h>
    00046 #include <netinet/ip.h>
    00047 #include <unistd.h>
    00048 #include <stdlib.h>
    00049 #include <netdb.h>
    00050 #include <stdio.h>
    00051 #include <string.h>
    00052 #include <errno.h>
    00053 #include <fcntl.h>
    00054 #ifdef __cplusplus
    00055 extern "C" {
    00056 #endif
    00057
    00058 #include "asterisk.h"
    00059
    00060 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211526 $")
    00061
    00062 #include "asterisk/lock.h"
    00063 #include "asterisk/logger.h"
    00064 #include "asterisk/channel.h"
    00065 #include "asterisk/config.h"
    00066 #include "asterisk/module.h"
    00067 #include "asterisk/pbx.h"
    00068 #include "asterisk/options.h"
    00069 #include "asterisk/utils.h"
    00070 #include "asterisk/lock.h"
    00071 #include "asterisk/sched.h"
    00072 #include "asterisk/io.h"
    00073 #include "asterisk/rtp.h"
    00074 #include "asterisk/acl.h"
    00075 #include "asterisk/callerid.h"
    00076 #include "asterisk/cli.h"
    00077 #include "asterisk/dsp.h"
    00078 #include "asterisk/causes.h"
    00079 #ifdef __cplusplus
    00080 }
    00081 #endif
    00082 #include "h323/chan_h323.h"
    00083
    00084 send_digit_cb on_send_digit;
    00085 on_rtp_cb on_external_rtp_create;
    00086 start_rtp_cb on_start_rtp_channel;
    00087 setup_incoming_cb on_incoming_call;
    00088 setup_outbound_cb on_outgoing_call;
    00089 chan_ringing_cb   on_chan_ringing;
    00090 con_established_cb on_connection_established;
    00091 clear_con_cb on_connection_cleared;
    00092 answer_call_cb on_answer_call;
    00093 progress_cb on_progress;
    00094 rfc2833_cb on_set_rfc2833_payload;
    00095 hangup_cb on_hangup;
    00096 setcapabilities_cb on_setcapabilities;
    00097
    00098 /* global debug flag */
    00099 int h323debug;
    00100
    00101 /** Variables required by Asterisk */
    00102 static const char type[] = "H323";
    00103 static const char desc[] = "The NuFone Network's Open H.323 Channel Driver";
    00104 static const char tdesc[] = "The NuFone Network's Open H.323 Channel Driver";
    00105 static const char config[] = "h323.conf";
    00106 static char default_context[AST_MAX_CONTEXT] = "default";
    00107 static struct sockaddr_in bindaddr;
    00108
    00109 /** H.323 configuration values */
    00110 static int h323_signalling_port = 1720;
    00111 static char gatekeeper[100];
    00112 static int gatekeeper_disable = 1;
    00113 static int gatekeeper_discover = 0;
    00114 static int usingGk = 0;
    00115 static int gkroute = 0;
    00116 /* Find user by alias (h.323 id) is default, alternative is the incomming call's source IP address*/
    00117 static int userbyalias = 1;
    00118 static int tos = 0;
    00119 static char secret[50];
    00120 static unsigned int unique = 0;
    00121
    00122 static call_options_t global_options;
    00123
    00124 /** Private structure of a OpenH323 channel */
    00125 struct oh323_pvt {
    00126    ast_mutex_t lock;             /* Channel private lock */
    00127    call_options_t options;             /* Options to be used during call setup */
    00128    int alreadygone;              /* Whether or not we've already been destroyed by our peer */
    00129    int needdestroy;              /* if we need to be destroyed */
    00130    call_details_t cd;               /* Call details */
    00131    struct ast_channel *owner;          /* Who owns us */
    00132    struct sockaddr_in sa;                       /* Our peer */
    00133    struct sockaddr_in redirip;                 /* Where our RTP should be going if not to us */
    00134    int nonCodecCapability;             /* non-audio capability */
    00135    int outgoing;                 /* Outgoing or incoming call? */
    00136    char exten[AST_MAX_EXTENSION];            /* Requested extension */
    00137    char context[AST_MAX_CONTEXT];            /* Context where to start */
    00138    char accountcode[256];              /* Account code */
    00139    char cid_num[80];             /* Caller*id number, if available */
    00140    char cid_name[80];               /* Caller*id name, if available */
    00141    char rdnis[80];                  /* Referring DNIS, if available */
    00142    int amaflags;                 /* AMA Flags */
    00143    struct ast_rtp *rtp;             /* RTP Session */
    00144    struct ast_dsp *vad;             /* Used for in-band DTMF detection */
    00145    int nativeformats;               /* Codec formats supported by a channel */
    00146    int needhangup;                  /* Send hangup when Asterisk is ready */
    00147    int hangupcause;              /* Hangup cause from OpenH323 layer */
    00148    int newstate;                 /* Pending state change */
    00149    int newcontrol;                  /* Pending control to send */
    00150    struct oh323_pvt *next;          /* Next channel in list */
    00151 } *iflist = NULL;
    00152
    00153 static struct ast_user_list {
    00154    struct oh323_user *users;
    00155    ast_mutex_t lock;
    00156 } userl;
    00157
    00158 static struct ast_peer_list {
    00159    struct oh323_peer *peers;
    00160    ast_mutex_t lock;
    00161 } peerl;
    00162
    00163 static struct ast_alias_list {
    00164    struct oh323_alias *aliases;
    00165    ast_mutex_t lock;
    00166 } aliasl;
    00167
    00168 /** Asterisk RTP stuff */
    00169 static struct sched_context *sched;
    00170 static struct io_context *io;
    00171
    00172 /** Protect the interface list (oh323_pvt) */
    00173 AST_MUTEX_DEFINE_STATIC(iflock);
    00174
    00175 /** Usage counter and associated lock */
    00176 static int usecnt = 0;
    00177 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
    00178
    00179 /* Protect the monitoring thread, so only one process can kill or start it, and not
    00180    when it's doing something critical. */
    00181 AST_MUTEX_DEFINE_STATIC(monlock);
    00182
    00183 /* Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack. */
    00184 AST_MUTEX_DEFINE_STATIC(caplock);
    00185
    00186 /* Protect the reload process */
    00187 AST_MUTEX_DEFINE_STATIC(h323_reload_lock);
    00188 static int h323_reloading = 0;
    00189
    00190 /* This is the thread for the monitor which checks for input on the channels
    00191    which are not currently in use.  */
    00192 static pthread_t monitor_thread = AST_PTHREADT_NULL;
    00193 static int restart_monitor(void);
    00194 static int h323_do_reload(void);
    00195
    00196 static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause);
    00197 static int oh323_digit(struct ast_channel *c, char digit);
    00198 static int oh323_call(struct ast_channel *c, char *dest, int timeout);
    00199 static int oh323_hangup(struct ast_channel *c);
    00200 static int oh323_answer(struct ast_channel *c);
    00201 static struct ast_frame *oh323_read(struct ast_channel *c);
    00202 static int oh323_write(struct ast_channel *c, struct ast_frame *frame);
    00203 static int oh323_indicate(struct ast_channel *c, int condition);
    00204 static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
    00205
    00206 static const struct ast_channel_tech oh323_tech = {
    00207    .type = type,
    00208    .description = tdesc,
    00209    .capabilities = AST_FORMAT_ULAW,
    00210    .properties = AST_CHAN_TP_WANTSJITTER,
    00211    .requester = oh323_request,
    00212    .send_digit = oh323_digit,
    00213    .call = oh323_call,
    00214    .hangup = oh323_hangup,
    00215    .answer = oh323_answer,
    00216    .read = oh323_read,
    00217    .write = oh323_write,
    00218    .indicate = oh323_indicate,
    00219    .fixup = oh323_fixup,
    00220    /* disable, for now */
    00221 #if 0
    00222    .bridge = ast_rtp_bridge,
    00223 #endif
    00224 };
    00225
    00226 /* Channel and private structures should be already locked */
    00227 static void __oh323_update_info(struct ast_channel *c, struct oh323_pvt *pvt)
    00228 {
    00229    if (c->nativeformats != pvt->nativeformats) {
    00230       if (h323debug)
    00231          ast_log(LOG_DEBUG, "Preparing %s for new native format\n", c->name);
    00232       c->nativeformats = pvt->nativeformats;
    00233       ast_set_read_format(c, c->readformat);
    00234       ast_set_write_format(c, c->writeformat);
    00235    }
    00236    if (pvt->needhangup) {
    00237       if (h323debug)
    00238          ast_log(LOG_DEBUG, "Process pending hangup for %s\n", c->name);
    00239       c->_softhangup |= AST_SOFTHANGUP_DEV;
    00240       c->hangupcause = pvt->hangupcause;
    00241       ast_queue_hangup(c);
    00242       pvt->needhangup = 0;
    00243       pvt->newstate = pvt->newcontrol = -1;
    00244    }
    00245    if (pvt->newstate >= 0) {
    00246       ast_setstate(c, pvt->newstate);
    00247       pvt->newstate = -1;
    00248    }
    00249    if (pvt->newcontrol >= 0) {
    00250       ast_queue_control(c, pvt->newcontrol);
    00251       pvt->newcontrol = -1;
    00252    }
    00253 }
    00254
    00255 /* Only channel structure should be locked */
    00256 static void oh323_update_info(struct ast_channel *c)
    00257 {
    00258    struct oh323_pvt *pvt = c->tech_pvt;
    00259
    00260    if (pvt) {
    00261       ast_mutex_lock(&pvt->lock);
    00262       __oh323_update_info(c, pvt);
    00263       ast_mutex_unlock(&pvt->lock);
    00264    }
    00265 }
    00266
    00267 static void cleanup_call_details(call_details_t *cd)
    00268 {
    00269         if (cd->call_token) {
    00270                 free(cd->call_token);
    00271                 cd->call_token = NULL;
    00272         }
    00273         if (cd->call_source_aliases) {
    00274                 free(cd->call_source_aliases);
    00275                 cd->call_source_aliases = NULL;
    00276         }
    00277         if (cd->call_dest_alias) {
    00278                 free(cd->call_dest_alias);
    00279                 cd->call_dest_alias = NULL;
    00280    }
    00281         if (cd->call_source_name) {
    00282                 free(cd->call_source_name);
    00283                 cd->call_source_name = NULL;
    00284         }
    00285         if (cd->call_source_e164) {
    00286                 free(cd->call_source_e164);
    00287                 cd->call_source_e164 = NULL;
    00288         }
    00289         if (cd->call_dest_e164) {
    00290                 free(cd->call_dest_e164);
    00291                 cd->call_dest_e164 = NULL;
    00292         }
    00293         if (cd->sourceIp) {
    00294                 free(cd->sourceIp);
    00295                 cd->sourceIp = NULL;
    00296         }
    00297 }
    00298
    00299 static void __oh323_destroy(struct oh323_pvt *pvt)
    00300 {
    00301    struct oh323_pvt *cur, *prev = NULL;
    00302
    00303    if (pvt->rtp) {
    00304       ast_rtp_destroy(pvt->rtp);
    00305    }
    00306
    00307    /* Free dsp used for in-band DTMF detection */
    00308    if (pvt->vad) {
    00309       ast_dsp_free(pvt->vad);
    00310    }
    00311    cleanup_call_details(&pvt->cd);
    00312
    00313    /* Unlink us from the owner if we have one */
    00314    if (pvt->owner) {
    00315       ast_mutex_lock(&pvt->owner->lock);
    00316       ast_log(LOG_DEBUG, "Detaching from %s\n", pvt->owner->name);
    00317       pvt->owner->tech_pvt = NULL;
    00318       ast_mutex_unlock(&pvt->owner->lock);
    00319    }
    00320    cur = iflist;
    00321    while(cur) {
    00322       if (cur == pvt) {
    00323          if (prev)
    00324             prev->next = cur->next;
    00325          else
    00326             iflist = cur->next;
    00327          break;
    00328       }
    00329       prev = cur;
    00330       cur = cur->next;
    00331    }
    00332    if (!cur) {
    00333       ast_log(LOG_WARNING, "%p is not in list?!?! \n", cur);
    00334    } else {
    00335       ast_mutex_destroy(&pvt->lock);
    00336       free(pvt);
    00337    }
    00338 }
    00339
    00340 static void oh323_destroy(struct oh323_pvt *pvt)
    00341 {
    00342    ast_mutex_lock(&iflock);
    00343    __oh323_destroy(pvt);
    00344    ast_mutex_unlock(&iflock);
    00345 }
    00346
    00347 /**
    00348  * Send (play) the specified digit to the channel.
    00349  *
    00350  */
    00351 static int oh323_digit(struct ast_channel *c, char digit)
    00352 {
    00353    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
    00354    char *token;
    00355
    00356    if (!pvt) {
    00357       ast_log(LOG_ERROR, "No private structure?! This is bad\n");
    00358       return -1;
    00359    }
    00360    ast_mutex_lock(&pvt->lock);
    00361    if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833)) {
    00362       /* out-of-band DTMF */
    00363       if (h323debug) {
    00364          ast_log(LOG_DEBUG, "Sending out-of-band digit %c on %s\n", digit, c->name);
    00365       }
    00366       ast_rtp_senddigit(pvt->rtp, digit);
    00367    } else {
    00368       /* in-band DTMF */
    00369       if (h323debug) {
    00370          ast_log(LOG_DEBUG, "Sending inband digit %c on %s\n", digit, c->name);
    00371       }
    00372       token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
    00373       h323_send_tone(token, digit);
    00374       if (token) {
    00375          free(token);
    00376       }
    00377    }
    00378    ast_mutex_unlock(&pvt->lock);
    00379    oh323_update_info(c);
    00380    return 0;
    00381 }
    00382
    00383 /**
    00384  * Make a call over the specified channel to the specified
    00385  * destination.
    00386  * Returns -1 on error, 0 on success.
    00387  */
    00388 static int oh323_call(struct ast_channel *c, char *dest, int timeout)
    00389 {
    00390    int res = 0;
    00391    struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;
    00392    char addr[INET_ADDRSTRLEN];
    00393    char called_addr[1024];
    00394
    00395    if (h323debug) {
    00396       ast_log(LOG_DEBUG, "Calling to %s on %s\n", dest, c->name);
    00397    }
    00398    if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
    00399       ast_log(LOG_WARNING, "Line is already in use (%s)\n", c->name);
    00400       return -1;
    00401    }
    00402    ast_mutex_lock(&pvt->lock);
    00403    if (usingGk) {
    00404       if (ast_strlen_zero(pvt->exten)) {
    00405          strncpy(called_addr, dest, sizeof(called_addr));
    00406       } else {
    00407          snprintf(called_addr, sizeof(called_addr), "%s@%s", pvt->exten, dest);
    00408       }
    00409    } else {
    00410       ast_inet_ntoa(addr, sizeof(addr), pvt->sa.sin_addr);
    00411       res = htons(pvt->sa.sin_port);
    00412       if (ast_strlen_zero(pvt->exten)) {
    00413          snprintf(called_addr, sizeof(called_addr), "%s:%d", addr, res);
    00414       } else {
    00415          snprintf(called_addr, sizeof(called_addr), "%s@%s:%d", pvt->exten, addr, res);
    00416       }
    00417    }
    00418    /* make sure null terminated */
    00419    called_addr[sizeof(called_addr) - 1] = '\0';
    00420
    00421    if (c->cid.cid_num) {
    00422       strncpy(pvt->options.cid_num, c->cid.cid_num, sizeof(pvt->options.cid_num));
    00423    }
    00424    if (c->cid.cid_name) {
    00425       strncpy(pvt->options.cid_name, c->cid.cid_name, sizeof(pvt->options.cid_name));
    00426    }
    00427
    00428    /* indicate that this is an outgoing call */
    00429    pvt->outgoing = 1;
    00430
    00431    ast_log(LOG_DEBUG, "Placing outgoing call to %s, %d\n", called_addr, pvt->options.dtmfcodec);
    00432    ast_mutex_unlock(&pvt->lock);
    00433    res = h323_make_call(called_addr, &(pvt->cd), &pvt->options);
    00434    if (res) {
    00435       ast_log(LOG_NOTICE, "h323_make_call failed(%s)\n", c->name);
    00436       return -1;
    00437    }
    00438    oh323_update_info(c);
    00439    return 0;
    00440 }
    00441
    00442 static int oh323_answer(struct ast_channel *c)
    00443 {
    00444    int res;
    00445    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
    00446    char *token;
    00447
    00448    if (h323debug)
    00449       ast_log(LOG_DEBUG, "Answering on %s\n", c->name);
    00450
    00451    ast_mutex_lock(&pvt->lock);
    00452    token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
    00453    ast_mutex_unlock(&pvt->lock);
    00454    res = h323_answering_call(token, 0);
    00455    if (token)
    00456       free(token);
    00457
    00458    oh323_update_info(c);
    00459    if (c->_state != AST_STATE_UP) {
    00460       ast_setstate(c, AST_STATE_UP);
    00461    }
    00462    return res;
    00463 }
    00464
    00465 static int oh323_hangup(struct ast_channel *c)
    00466 {
    00467    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
    00468    int needcancel = 0;
    00469    int q931cause = AST_CAUSE_NORMAL_CLEARING;
    00470    char *call_token;
    00471
    00472
    00473    if (h323debug)
    00474       ast_log(LOG_DEBUG, "Hanging up call %s\n", c->name);
    00475
    00476    if (!c->tech_pvt) {
    00477       ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
    00478       return 0;
    00479    }
    00480    ast_mutex_lock(&pvt->lock);
    00481    /* Determine how to disconnect */
    00482    if (pvt->owner != c) {
    00483       ast_log(LOG_WARNING, "Huh?  We aren't the owner?\n");
    00484       ast_mutex_unlock(&pvt->lock);
    00485       return 0;
    00486    }
    00487    if (!c || (c->_state != AST_STATE_UP)) {
    00488       needcancel = 1;
    00489    }
    00490
    00491    pvt->owner = NULL;
    00492    c->tech_pvt = NULL;
    00493
    00494    if (c->hangupcause) {
    00495       q931cause = c->hangupcause;
    00496    } else {
    00497       char *cause = pbx_builtin_getvar_helper(c, "DIALSTATUS");
    00498       if (cause) {
    00499          if (!strcmp(cause, "CONGESTION")) {
    00500             q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
    00501          } else if (!strcmp(cause, "BUSY")) {
    00502             q931cause = AST_CAUSE_USER_BUSY;
    00503          } else if (!strcmp(cause, "CHANISUNVAIL")) {
    00504             q931cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
    00505          } else if (!strcmp(cause, "NOANSWER")) {
    00506             q931cause = AST_CAUSE_NO_ANSWER;
    00507          } else if (!strcmp(cause, "CANCEL")) {
    00508             q931cause = AST_CAUSE_CALL_REJECTED;
    00509          }
    00510       }
    00511    }
    00512
    00513    /* Start the process if it's not already started */
    00514    if (!pvt->alreadygone && !pvt->hangupcause) {
    00515       call_token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
    00516       if (call_token) {
    00517          /* Release lock to eliminate deadlock */
    00518          ast_mutex_unlock(&pvt->lock);
    00519          if (h323_clear_call(call_token, q931cause)) {
    00520             ast_log(LOG_DEBUG, "ClearCall failed.\n");
    00521          }
    00522          free(call_token);
    00523          ast_mutex_lock(&pvt->lock);
    00524       }
    00525    }
    00526    pvt->needdestroy = 1;
    00527
    00528    /* Update usage counter */
    00529    ast_mutex_lock(&usecnt_lock);
    00530    usecnt--;
    00531    if (usecnt < 0) {
    00532       ast_log(LOG_WARNING, "Usecnt < 0\n");
    00533    }
    00534    ast_mutex_unlock(&usecnt_lock);
    00535    ast_mutex_unlock(&pvt->lock);
    00536    ast_update_use_count();
    00537    return 0;
    00538 }
    00539
    00540 static struct ast_frame *oh323_rtp_read(struct oh323_pvt *pvt)
    00541 {
    00542    /* Retrieve audio/etc from channel.  Assumes pvt->lock is already held. */
    00543    struct ast_frame *f;
    00544    static struct ast_frame null_frame = { AST_FRAME_NULL, };
    00545
    00546    /* Only apply it for the first packet, we just need the correct ip/port */
    00547    if (pvt->options.nat) {
    00548       ast_rtp_setnat(pvt->rtp, pvt->options.nat);
    00549       pvt->options.nat = 0;
    00550    }
    00551
    00552    f = ast_rtp_read(pvt->rtp);
    00553    /* Don't send RFC2833 if we're not supposed to */
    00554    if (f && (f->frametype == AST_FRAME_DTMF) && !(pvt->options.dtmfmode & H323_DTMF_RFC2833)) {
    00555       return &null_frame;
    00556    }
    00557    if (pvt->owner) {
    00558       /* We already hold the channel lock */
    00559       if (f->frametype == AST_FRAME_VOICE) {
    00560          if (f->subclass != pvt->owner->nativeformats) {
    00561             /* Try to avoid deadlock */
    00562             if (ast_mutex_trylock(&pvt->owner->lock)) {
    00563                ast_log(LOG_NOTICE, "Format changed but channel is locked. Ignoring frame...\n");
    00564                return &null_frame;
    00565             }
    00566             ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
    00567             pvt->owner->nativeformats = f->subclass;
    00568             pvt->nativeformats = f->subclass;
    00569             ast_set_read_format(pvt->owner, pvt->owner->readformat);
    00570             ast_set_write_format(pvt->owner, pvt->owner->writeformat);
    00571             ast_mutex_unlock(&pvt->owner->lock);
    00572          }
    00573          /* Do in-band DTMF detection */
    00574          if ((pvt->options.dtmfmode & H323_DTMF_INBAND) && pvt->vad) {
    00575             if (!ast_mutex_trylock(&pvt->owner->lock)) {
    00576                f = ast_dsp_process(pvt->owner,pvt->vad,f);
    00577                ast_mutex_unlock(&pvt->owner->lock);
    00578             }
    00579             else
    00580                ast_log(LOG_NOTICE, "Unable to process inband DTMF while channel is locked\n");
    00581             if (f &&(f->frametype == AST_FRAME_DTMF)) {
    00582                ast_log(LOG_DEBUG, "Received in-band digit %c.\n", f->subclass);
    00583             }
    00584          }
    00585       }
    00586    }
    00587    return f;
    00588 }
    00589
    00590 static struct ast_frame *oh323_read(struct ast_channel *c)
    00591 {
    00592    struct ast_frame *fr;
    00593    struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;
    00594    ast_mutex_lock(&pvt->lock);
    00595    __oh323_update_info(c, pvt);
    00596    fr = oh323_rtp_read(pvt);
    00597    ast_mutex_unlock(&pvt->lock);
    00598    return fr;
    00599 }
    00600
    00601 static int oh323_write(struct ast_channel *c, struct ast_frame *frame)
    00602 {
    00603    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
    00604    int res = 0;
    00605    if (frame->frametype != AST_FRAME_VOICE) {
    00606       if (frame->frametype == AST_FRAME_IMAGE) {
    00607          return 0;
    00608       } else {
    00609          ast_log(LOG_WARNING, "Can't send %d type frames with H323 write\n", frame->frametype);
    00610          return 0;
    00611       }
    00612    } else {
    00613       if (!(frame->subclass & c->nativeformats)) {
    00614          ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
    00615             frame->subclass, c->nativeformats, c->readformat, c->writeformat);
    00616          return 0;
    00617       }
    00618    }
    00619    if (pvt) {
    00620       ast_mutex_lock(&pvt->lock);
    00621       if (pvt->rtp) {
    00622          res =  ast_rtp_write(pvt->rtp, frame);
    00623       }
    00624       __oh323_update_info(c, pvt);
    00625       ast_mutex_unlock(&pvt->lock);
    00626    }
    00627    return res;
    00628 }
    00629
    00630 static int oh323_indicate(struct ast_channel *c, int condition)
    00631 {
    00632
    00633    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
    00634    char *token = (char *)NULL;
    00635
    00636    ast_mutex_lock(&pvt->lock);
    00637    token = (pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL);
    00638    ast_mutex_unlock(&pvt->lock);
    00639
    00640    if (h323debug)
    00641       ast_log(LOG_DEBUG, "OH323: Indicating %d on %s\n", condition, token);
    00642
    00643    switch(condition) {
    00644    case AST_CONTROL_RINGING:
    00645       if (c->_state == AST_STATE_RING || c->_state == AST_STATE_RINGING) {
    00646          h323_send_alerting(token);
    00647          break;
    00648       }
    00649       if (token)
    00650          free(token);
    00651       return -1;
    00652    case AST_CONTROL_PROGRESS:
    00653       if (c->_state != AST_STATE_UP) {
    00654          h323_send_progress(token);
    00655          break;
    00656       }
    00657       if (token)
    00658          free(token);
    00659       return -1;
    00660
    00661    case AST_CONTROL_BUSY:
    00662       if (c->_state != AST_STATE_UP) {
    00663          h323_answering_call(token, 1);
    00664          ast_mutex_lock(&pvt->lock);
    00665          pvt->alreadygone = 1;
    00666          ast_mutex_unlock(&pvt->lock);
    00667          ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
    00668          break;
    00669       }
    00670       if (token)
    00671          free(token);
    00672       return -1;
    00673    case AST_CONTROL_CONGESTION:
    00674       if (c->_state != AST_STATE_UP) {
    00675          h323_answering_call(token, 1);
    00676          ast_mutex_lock(&pvt->lock);
    00677          pvt->alreadygone = 1;
    00678          ast_mutex_unlock(&pvt->lock);
    00679          ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
    00680          break;
    00681       }
    00682       if (token)
    00683          free(token);
    00684       return -1;
    00685    case AST_CONTROL_PROCEEDING:
    00686    case -1:
    00687       if (token)
    00688          free(token);
    00689       return -1;
    00690    default:
    00691       ast_log(LOG_WARNING, "Don't know how to indicate condition %d on %s\n", condition, token);
    00692       if (token)
    00693          free(token);
    00694       return -1;
    00695    }
    00696
    00697    if (h323debug)
    00698       ast_log(LOG_DEBUG, "OH323: Indicated %d on %s\n", condition, token);
    00699    if (token)
    00700       free(token);
    00701    oh323_update_info(c);
    00702
    00703    return -1;
    00704 }
    00705
    00706 static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
    00707 {
    00708    struct oh323_pvt *pvt = (struct oh323_pvt *) newchan->tech_pvt;
    00709
    00710    ast_mutex_lock(&pvt->lock);
    00711    if (pvt->owner != oldchan) {
    00712       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, pvt->owner);
    00713       return -1;
    00714    }
    00715    pvt->owner = newchan;
    00716    ast_mutex_unlock(&pvt->lock);
    00717    return 0;
    00718 }
    00719
    00720 /* Private structure should be locked on a call */
    00721 static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const char *host)
    00722 {
    00723    struct ast_channel *ch;
    00724    int fmt;
    00725
    00726    /* Don't hold a oh323_pvt lock while we allocate a chanel */
    00727    ast_mutex_unlock(&pvt->lock);
    00728    ch = ast_channel_alloc(1);
    00729    /* Update usage counter */
    00730    ast_mutex_lock(&usecnt_lock);
    00731    usecnt++;
    00732    ast_mutex_unlock(&usecnt_lock);
    00733    ast_update_use_count();
    00734    ast_mutex_lock(&pvt->lock);
    00735    if (ch) {
    00736       ch->tech = &oh323_tech;
    00737       snprintf(ch->name, sizeof(ch->name), "H323/%s", host);
    00738       ch->nativeformats = pvt->options.capability;
    00739       if (!ch->nativeformats) {
    00740          ch->nativeformats = global_options.capability;
    00741       }
    00742       pvt->nativeformats = ch->nativeformats;
    00743       fmt = ast_best_codec(ch->nativeformats);
    00744       ch->type = type;
    00745       ch->fds[0] = ast_rtp_fd(pvt->rtp);
    00746       if (state == AST_STATE_RING) {
    00747          ch->rings = 1;
    00748       }
    00749       ch->writeformat = fmt;
    00750       ch->rawwriteformat = fmt;
    00751       ch->readformat = fmt;
    00752       ch->rawreadformat = fmt;
    00753       /* Allocate dsp for in-band DTMF support */
    00754       if (pvt->options.dtmfmode & H323_DTMF_INBAND) {
    00755          pvt->vad = ast_dsp_new();
    00756          ast_dsp_set_features(pvt->vad, DSP_FEATURE_DTMF_DETECT);
    00757          }
    00758       /* Register channel functions. */
    00759       ch->tech_pvt = pvt;
    00760       /*  Set the owner of this channel */
    00761       pvt->owner = ch;
    00762
    00763       strncpy(ch->context, pvt->context, sizeof(ch->context) - 1);
    00764       strncpy(ch->exten, pvt->exten, sizeof(ch->exten) - 1);
    00765       ch->priority = 1;
    00766       if (!ast_strlen_zero(pvt->accountcode)) {
    00767          strncpy(ch->accountcode, pvt->accountcode, sizeof(ch->accountcode) - 1);
    00768       }
    00769       if (pvt->amaflags) {
    00770          ch->amaflags = pvt->amaflags;
    00771       }
    00772
    00773       if (!ast_strlen_zero(pvt->cid_num))
    00774          ch->cid.cid_num = strdup(pvt->cid_num);
    00775       else if (!ast_strlen_zero(pvt->cd.call_source_e164))
    00776          ch->cid.cid_num = strdup(pvt->cd.call_source_e164);
    00777       if (!ast_strlen_zero(pvt->cid_name))
    00778          ch->cid.cid_name = strdup(pvt->cid_name);
    00779
    00780       if (!ast_strlen_zero(pvt->rdnis)) {
    00781          ch->cid.cid_rdnis = strdup(pvt->rdnis);
    00782       }
    00783       if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) {
    00784          ch->cid.cid_dnid = strdup(pvt->exten);
    00785       }
    00786       ast_setstate(ch, state);
    00787       if (state != AST_STATE_DOWN) {
    00788          if (ast_pbx_start(ch)) {
    00789             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name);
    00790             ast_hangup(ch);
    00791             ch = NULL;
    00792          }
    00793       }
    00794    } else  {
    00795       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
    00796    }
    00797    return ch;
    00798 }
    00799
    00800 static struct oh323_pvt *oh323_alloc(int callid)
    00801 {
    00802    struct oh323_pvt *pvt;
    00803
    00804    pvt = (struct oh323_pvt *) malloc(sizeof(struct oh323_pvt));
    00805    if (!pvt) {
    00806       ast_log(LOG_ERROR, "Couldn't allocate private structure. This is bad\n");
    00807       return NULL;
    00808    }
    00809    memset(pvt, 0, sizeof(struct oh323_pvt));
    00810    pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0,bindaddr.sin_addr);
    00811    if (!pvt->rtp) {
    00812       ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
    00813       free(pvt);
    00814       return NULL;
    00815    }
    00816    ast_rtp_settos(pvt->rtp, tos);
    00817    ast_mutex_init(&pvt->lock);
    00818    /* Ensure the call token is allocated */
    00819    if ((pvt->cd).call_token == NULL) {
    00820       (pvt->cd).call_token = (char *)malloc(128);
    00821    }
    00822    if (!pvt->cd.call_token) {
    00823       ast_log(LOG_ERROR, "Not enough memory to alocate call token\n");
    00824       return NULL;
    00825    }
    00826    memset((char *)(pvt->cd).call_token, 0, 128);
    00827    pvt->cd.call_reference = callid;
    00828    memcpy(&pvt->options, &global_options, sizeof(pvt->options));
    00829    if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
    00830       pvt->nonCodecCapability |= AST_RTP_DTMF;
    00831    } else {
    00832       pvt->nonCodecCapability &= ~AST_RTP_DTMF;
    00833    }
    00834    strncpy(pvt->context, default_context, sizeof(pvt->context) - 1);
    00835    pvt->newstate = pvt->newcontrol = -1;
    00836    /* Add to interface list */
    00837    ast_mutex_lock(&iflock);
    00838    pvt->next = iflist;
    00839    iflist = pvt;
    00840    ast_mutex_unlock(&iflock);
    00841    return pvt;
    00842 }
    00843
    00844 static struct oh323_pvt *find_call_locked(int call_reference, const char *token)
    00845 {
    00846    struct oh323_pvt *pvt;
    00847
    00848    ast_mutex_lock(&iflock);
    00849    pvt = iflist;
    00850    while(pvt) {
    00851       if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) {
    00852          /* Found the call */
    00853          if ((token != NULL) && (!strcmp(pvt->cd.call_token, token))) {
    00854             ast_mutex_lock(&pvt->lock);
    00855             ast_mutex_unlock(&iflock);
    00856             return pvt;
    00857          } else if (token == NULL) {
    00858             ast_log(LOG_WARNING, "Call Token is NULL\n");
    00859             ast_mutex_lock(&pvt->lock);
    00860             ast_mutex_unlock(&iflock);
    00861             return pvt;
    00862          }
    00863       }
    00864       pvt = pvt->next;
    00865    }
    00866    ast_mutex_unlock(&iflock);
    00867    return NULL;
    00868 }
    00869
    00870 static int update_state(struct oh323_pvt *pvt, int state, int signal)
    00871 {
    00872    if (!pvt)
    00873       return 0;
    00874    if (pvt->owner && !ast_mutex_trylock(&pvt->owner->lock)) {
    00875       if (state >= 0)
    00876          ast_setstate(pvt->owner, state);
    00877       if (signal >= 0)
    00878          ast_queue_control(pvt->owner, signal);
    00879       return 1;
    00880    }
    00881    else {
    00882       if (state >= 0)
    00883          pvt->newstate = state;
    00884       if (signal >= 0)
    00885          pvt->newcontrol = signal;
    00886       return 0;
    00887    }
    00888 }
    00889
    00890 struct oh323_user *find_user(const call_details_t *cd)
    00891 {
    00892    struct oh323_user *u;
    00893    char iabuf[INET_ADDRSTRLEN];
    00894    u = userl.users;
    00895    if (userbyalias) {
    00896       while(u) {
    00897          if (!strcasecmp(u->name, cd->call_source_aliases)) {
    00898             break;
    00899          }
    00900          u = u->next;
    00901       }
    00902    } else {
    00903       while(u) {
    00904          if (!strcasecmp(cd->sourceIp, ast_inet_ntoa(iabuf, sizeof(iabuf), u->addr.sin_addr))) {
    00905             break;
    00906          }
    00907          u = u->next;
    00908       }
    00909    }
    00910    return u;
    00911 }
    00912
    00913 struct oh323_peer *find_peer(const char *peer, struct sockaddr_in *sin)
    00914 {
    00915    struct oh323_peer *p = NULL;
    00916          static char iabuf[INET_ADDRSTRLEN];
    00917
    00918    p = peerl.peers;
    00919    if (peer) {
    00920       while(p) {
    00921          if (!strcasecmp(p->name, peer)) {
    00922             ast_log(LOG_DEBUG, "Found peer %s by name\n", peer);
    00923             break;
    00924          }
    00925          p = p->next;
    00926       }
    00927    } else {
    00928       /* find by sin */
    00929       if (sin) {
    00930          while (p) {
    00931             if ((!inaddrcmp(&p->addr, sin)) ||
    00932                (p->addr.sin_addr.s_addr == sin->sin_addr.s_addr)) {
    00933                ast_log(LOG_DEBUG, "Found peer %s/%s by addr\n", peer, ast_inet_ntoa(iabuf, sizeof(iabuf), p->addr.sin_addr));
    00934                break;
    00935             }
    00936             p = p->next;
    00937          }
    00938       }
    00939    }
    00940    if (!p) {
    00941       ast_log(LOG_DEBUG, "Could not find peer %s by name or address\n", peer);
    00942    }
    00943    return p;
    00944 }
    00945
    00946 static int create_addr(struct oh323_pvt *pvt, char *opeer)
    00947 {
    00948    struct hostent *hp;
    00949    struct ast_hostent ahp;
    00950    struct oh323_peer *p;
    00951    int portno;
    00952    int found = 0;
    00953    char *port;
    00954    char *hostn;
    00955    char peer[256] = "";
    00956
    00957    strncpy(peer, opeer, sizeof(peer) - 1);
    00958    port = strchr(peer, ':');
    00959    if (port) {
    00960       *port = '\0';
    00961       port++;
    00962    }
    00963    pvt->sa.sin_family = AF_INET;
    00964    ast_mutex_lock(&peerl.lock);
    00965    p = find_peer(peer, NULL);
    00966    if (p) {
    00967       found++;
    00968       memcpy(&pvt->options, &p->options, sizeof(pvt->options));
    00969       if (pvt->rtp) {
    00970          ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat);
    00971          ast_rtp_setnat(pvt->rtp, pvt->options.nat);
    00972       }
    00973       if (pvt->options.dtmfmode) {
    00974          if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
    00975             pvt->nonCodecCapability |= AST_RTP_DTMF;
    00976          } else {
    00977             pvt->nonCodecCapability &= ~AST_RTP_DTMF;
    00978          }
    00979       }
    00980       if (p->addr.sin_addr.s_addr) {
    00981          pvt->sa.sin_addr = p->addr.sin_addr;
    00982          pvt->sa.sin_port = p->addr.sin_port;
    00983       }
    00984    }
    00985    ast_mutex_unlock(&peerl.lock);
    00986    if (!p && !found) {
    00987       hostn = peer;
    00988       if (port) {
    00989          portno = atoi(port);
    00990       } else {
    00991          portno = h323_signalling_port;
    00992       }
    00993       hp = ast_gethostbyname(hostn, &ahp);
    00994       if (hp) {
    00995          memcpy(&pvt->options, &global_options, sizeof(pvt->options));
    00996          memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
    00997          pvt->sa.sin_port = htons(portno);
    00998          return 0;
    00999       } else {
    01000          ast_log(LOG_WARNING, "No such host: %s\n", peer);
    01001          return -1;
    01002       }
    01003    } else if (!p) {
    01004       return -1;
    01005    } else {
    01006       return 0;
    01007    }
    01008 }
    01009 static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause)
    01010 {
    01011    int oldformat;
    01012    struct oh323_pvt *pvt;
    01013    struct ast_channel *tmpc = NULL;
    01014    char *dest = (char *)data;
    01015    char *ext, *host;
    01016    char *h323id = NULL;
    01017    char tmp[256], tmp1[256];
    01018
    01019    ast_log(LOG_DEBUG, "type=%s, format=%d, data=%s.\n", type, format, (char *)data);
    01020    pvt = oh323_alloc(0);
    01021    if (!pvt) {
    01022       ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data);
    01023       return NULL;
    01024    }
    01025    oldformat = format;
    01026    format &= ((AST_FORMAT_MAX_AUDIO << 1) - 1);
    01027    if (!format) {
    01028       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
    01029       return NULL;
    01030    }
    01031    strncpy(tmp, dest, sizeof(tmp) - 1);
    01032    host = strchr(tmp, '@');
    01033    if (host) {
    01034       *host = '\0';
    01035       host++;
    01036       ext = tmp;
    01037    } else {
    01038       host = tmp;
    01039       ext = NULL;
    01040    }
    01041    strtok_r(host, "/", &(h323id));
    01042    if (!ast_strlen_zero(h323id)) {
    01043       h323_set_id(h323id);
    01044    }
    01045    if (ext) {
    01046       strncpy(pvt->exten, ext, sizeof(pvt->exten) - 1);
    01047    }
    01048    ast_log(LOG_DEBUG, "Extension: %s Host: %s\n",  pvt->exten, host);
    01049    if (!usingGk) {
    01050       if (create_addr(pvt, host)) {
    01051          oh323_destroy(pvt);
    01052          return NULL;
    01053       }
    01054    }
    01055    else {
    01056       memcpy(&pvt->options, &global_options, sizeof(pvt->options));
    01057       if (pvt->rtp) {
    01058          ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat);
    01059          ast_rtp_setnat(pvt->rtp, pvt->options.nat);
    01060       }
    01061       if (pvt->options.dtmfmode) {
    01062          if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
    01063             pvt->nonCodecCapability |= AST_RTP_DTMF;
    01064          } else {
    01065             pvt->nonCodecCapability &= ~AST_RTP_DTMF;
    01066          }
    01067       }
    01068    }
    01069
    01070    ast_mutex_lock(&caplock);
    01071    /* Generate unique channel identifier */
    01072    snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
    01073    tmp1[sizeof(tmp1)-1] = '\0';
    01074    ast_mutex_unlock(&caplock);
    01075
    01076    ast_mutex_lock(&pvt->lock);
    01077    tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1);
    01078    ast_mutex_unlock(&pvt->lock);
    01079    if (!tmpc) {
    01080       oh323_destroy(pvt);
    01081    }
    01082    ast_update_use_count();
    01083    restart_monitor();
    01084    return tmpc;
    01085 }
    01086
    01087 /** Find a call by alias */
    01088 struct oh323_alias *find_alias(const char *source_aliases)
    01089 {
    01090    struct oh323_alias *a;
    01091
    01092    a = aliasl.aliases;
    01093    while(a) {
    01094       if (!strcasecmp(a->name, source_aliases)) {
    01095          break;
    01096       }
    01097       a = a->next;
    01098    }
    01099    return a;
    01100 }
    01101
    01102 /**
    01103   * Callback for sending digits from H.323 up to asterisk
    01104   *
    01105   */
    01106 int send_digit(unsigned call_reference, char digit, const char *token)
    01107 {
    01108    struct oh323_pvt *pvt;
    01109    struct ast_frame f;
    01110    int res;
    01111
    01112    ast_log(LOG_DEBUG, "Received Digit: %c\n", digit);
    01113    pvt = find_call_locked(call_reference, token);
    01114    if (!pvt) {
    01115       ast_log(LOG_ERROR, "Private structure not found in send_digit.\n");
    01116       return -1;
    01117    }
    01118    memset(&f, 0, sizeof(f));
    01119    f.frametype = AST_FRAME_DTMF;
    01120    f.subclass = digit;
    01121    f.datalen = 0;
    01122    f.samples = 800;
    01123    f.offset = 0;
    01124    f.data = NULL;
    01125    f.mallocd = 0;
    01126    f.src = "SEND_DIGIT";
    01127    res = ast_queue_frame(pvt->owner, &f);
    01128    ast_mutex_unlock(&pvt->lock);
    01129    return res;
    01130 }
    01131
    01132 /**
    01133   * Callback function used to inform the H.323 stack of the local rtp ip/port details
    01134   *
    01135   * Returns the local RTP information
    01136   */
    01137 struct rtp_info *external_rtp_create(unsigned call_reference, const char * token)
    01138 {
    01139    struct oh323_pvt *pvt;
    01140    struct sockaddr_in us;
    01141    struct rtp_info *info;
    01142
    01143    info = (struct rtp_info *)malloc(sizeof(struct rtp_info));
    01144    if (!info) {
    01145       ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
    01146       return NULL;
    01147    }
    01148    pvt = find_call_locked(call_reference, token);
    01149    if (!pvt) {
    01150       free(info);
    01151       ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
    01152       return NULL;
    01153    }
    01154    /* figure out our local RTP port and tell the H.323 stack about it */
    01155    ast_rtp_get_us(pvt->rtp, &us);
    01156    ast_mutex_unlock(&pvt->lock);
    01157
    01158    ast_inet_ntoa(info->addr, sizeof(info->addr), us.sin_addr);
    01159    info->port = ntohs(us.sin_port);
    01160    if (h323debug)
    01161       ast_log(LOG_DEBUG, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
    01162    return info;
    01163 }
    01164
    01165 /**
    01166  * Definition taken from rtp.c for rtpPayloadType because we need it here.
    01167  */
    01168 struct rtpPayloadType {
    01169    int isAstFormat;        /* whether the following code is an AST_FORMAT */
    01170    int code;
    01171 };
    01172
    01173 /**
    01174   * Call-back function passing remote ip/port information from H.323 to asterisk
    01175   *
    01176   * Returns nothing
    01177   */
    01178 void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt)
    01179 {
    01180    struct oh323_pvt *pvt;
    01181    struct sockaddr_in them;
    01182    struct rtpPayloadType rtptype;
    01183
    01184    if (h323debug)
    01185       ast_log(LOG_DEBUG, "Setting up RTP connection for %s\n", token);
    01186
    01187    /* Find the call or allocate a private structure if call not found */
    01188    pvt = find_call_locked(call_reference, token);
    01189    if (!pvt) {
    01190       ast_log(LOG_ERROR, "Something is wrong: rtp\n");
    01191       return;
    01192    }
    01193    if (pvt->alreadygone) {
    01194       ast_mutex_unlock(&pvt->lock);
    01195       return;
    01196    }
    01197    rtptype = ast_rtp_lookup_pt(pvt->rtp, pt);
    01198    pvt->nativeformats = rtptype.code;
    01199    if (pvt->owner && !ast_mutex_trylock(&pvt->owner->lock)) {
    01200       pvt->owner->nativeformats = pvt->nativeformats;
    01201       ast_set_read_format(pvt->owner, pvt->owner->readformat);
    01202       ast_set_write_format(pvt->owner, pvt->owner->writeformat);
    01203       if (pvt->options.progress_audio)
    01204          ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);
    01205       ast_mutex_unlock(&pvt->owner->lock);
    01206    }
    01207    else {
    01208       if (pvt->options.progress_audio)
    01209          pvt->newcontrol = AST_CONTROL_PROGRESS;
    01210       if (h323debug)
    01211          ast_log(LOG_DEBUG, "RTP connection preparation for %s is pending...\n", token);
    01212    }
    01213
    01214    them.sin_family = AF_INET;
    01215    /* only works for IPv4 */
    01216    them.sin_addr.s_addr = inet_addr(remoteIp);
    01217    them.sin_port = htons(remotePort);
    01218    ast_rtp_set_peer(pvt->rtp, &them);
    01219
    01220    ast_mutex_unlock(&pvt->lock);
    01221
    01222    if (h323debug)
    01223       ast_log(LOG_DEBUG, "RTP connection prepared for %s\n", token);
    01224
    01225    return;
    01226 }
    01227
    01228 /**
    01229   *   Call-back function to signal asterisk that the channel has been answered
    01230   * Returns nothing
    01231   */
    01232 void connection_made(unsigned call_reference, const char *token)
    01233 {
    01234    struct oh323_pvt *pvt;
    01235
    01236    if (h323debug)
    01237       ast_log(LOG_DEBUG, "Call %s answered\n", token);
    01238
    01239    pvt = find_call_locked(call_reference, token);
    01240    if (!pvt) {
    01241       ast_log(LOG_ERROR, "Something is wrong: connection\n");
    01242       return;
    01243    }
    01244
    01245    /* Inform asterisk about remote party connected only on outgoing calls */
    01246    if (!pvt->outgoing) {
    01247       ast_mutex_unlock(&pvt->lock);
    01248       return;
    01249    }
    01250    if (update_state(pvt, AST_STATE_UP, AST_CONTROL_ANSWER))
    01251       ast_mutex_unlock(&pvt->owner->lock);
    01252    ast_mutex_unlock(&pvt->lock);
    01253    return;
    01254 }
    01255
    01256 int progress(unsigned call_reference, const char *token, int inband)
    01257 {
    01258    struct oh323_pvt *pvt;
    01259
    01260    ast_log(LOG_DEBUG, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
    01261
    01262    pvt = find_call_locked(call_reference, token);
    01263    if (!pvt) {
    01264       ast_log(LOG_ERROR, "Private structure not found in progress.\n");
    01265       return -1;
    01266    }
    01267    if (!pvt->owner) {
    01268       ast_mutex_unlock(&pvt->lock);
    01269       ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");
    01270       return -1;
    01271    }
    01272    if (update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING)))
    01273       ast_mutex_unlock(&pvt->owner->lock);
    01274    ast_mutex_unlock(&pvt->lock);
    01275
    01276    return 0;
    01277 }
    01278
    01279 /**
    01280  *  Call-back function for incoming calls
    01281  *
    01282  *  Returns 1 on success
    01283  */
    01284 call_options_t *setup_incoming_call(call_details_t *cd)
    01285 {
    01286    struct oh323_pvt *pvt;
    01287    struct oh323_user *user = NULL;
    01288    struct oh323_alias *alias = NULL;
    01289    char iabuf[INET_ADDRSTRLEN];
    01290
    01291    if (h323debug)
    01292       ast_log(LOG_DEBUG, "Setting up incoming call for %s\n", cd->call_token);
    01293
    01294    /* allocate the call*/
    01295    pvt = oh323_alloc(cd->call_reference);
    01296
    01297    if (!pvt) {
    01298       ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
    01299       return NULL;
    01300    }
    01301
    01302    /* Populate the call details in the private structure */
    01303    memcpy(&pvt->cd, cd, sizeof(pvt->cd));
    01304    memcpy(&pvt->options, &global_options, sizeof(pvt->options));
    01305
    01306    if (h323debug) {
    01307       ast_verbose(VERBOSE_PREFIX_3 "Setting up Call\n");
    01308       ast_verbose(VERBOSE_PREFIX_3 "\tCall token:  [%s]\n", pvt->cd.call_token);
    01309       ast_verbose(VERBOSE_PREFIX_3 "\tCalling party name:  [%s]\n", pvt->cd.call_source_name);
    01310       ast_verbose(VERBOSE_PREFIX_3 "\tCalling party number:  [%s]\n", pvt->cd.call_source_e164);
    01311       ast_verbose(VERBOSE_PREFIX_3 "\tCalled party name:  [%s]\n", pvt->cd.call_dest_alias);
    01312       ast_verbose(VERBOSE_PREFIX_3 "\tCalled party number:  [%s]\n", pvt->cd.call_dest_e164);
    01313    }
    01314
    01315    /* Decide if we are allowing Gatekeeper routed calls*/
    01316    if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && (usingGk)) {
    01317       if (!ast_strlen_zero(cd->call_dest_e164)) {
    01318          strncpy(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten) - 1);
    01319          strncpy(pvt->context, default_context, sizeof(pvt->context) - 1);
    01320       } else {
    01321          alias = find_alias(cd->call_dest_alias);
    01322          if (!alias) {
    01323             ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias);
    01324             return NULL;
    01325          }
    01326          strncpy(pvt->exten, alias->name, sizeof(pvt->exten) - 1);
    01327          strncpy(pvt->context, alias->context, sizeof(pvt->context) - 1);
    01328       }
    01329    } else {
    01330       /* Either this call is not from the Gatekeeper
    01331          or we are not allowing gk routed calls */
    01332       user  = find_user(cd);
    01333       if (!user) {
    01334          if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
    01335             strncpy(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten) - 1);
    01336          } else {
    01337             strncpy(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten) - 1);
    01338          }
    01339          if (ast_strlen_zero(default_context)) {
    01340             ast_log(LOG_ERROR, "Call from '%s' rejected due to no default context\n", pvt->cd.call_source_aliases);
    01341             return NULL;
    01342          }
    01343          strncpy(pvt->context, default_context, sizeof(pvt->context) - 1);
    01344          ast_log(LOG_DEBUG, "Sending %s to context [%s]\n", cd->call_source_aliases, pvt->context);
    01345          /* XXX: Is it really required??? */
    01346 #if 0
    01347          memset(&pvt->options, 0, sizeof(pvt->options));
    01348 #endif
    01349       } else {
    01350          if (user->host) {
    01351             if (strcasecmp(cd->sourceIp, ast_inet_ntoa(iabuf, sizeof(iabuf), user->addr.sin_addr))) {
    01352                if (ast_strlen_zero(user->context)) {
    01353                   if (ast_strlen_zero(default_context)) {
    01354                      ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp);
    01355                               return NULL;
    01356                   }
    01357                   strncpy(pvt->context, default_context, sizeof(pvt->context) - 1);
    01358                } else {
    01359                   strncpy(pvt->context, user->context, sizeof(pvt->context) - 1);
    01360                }
    01361                pvt->exten[0] = 'i';
    01362                pvt->exten[1] = '\0';
    01363                ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp);
    01364                return NULL;   /* XXX: Hmmm... Why to setup context if we drop connection immediately??? */
    01365             }
    01366          }
    01367          strncpy(pvt->context, user->context, sizeof(pvt->context) - 1);
    01368          memcpy(&pvt->options, &user->options, sizeof(pvt->options));
    01369          if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
    01370             strncpy(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten) - 1);
    01371          } else {
    01372             strncpy(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten) - 1);
    01373          }
    01374          if (!ast_strlen_zero(user->accountcode)) {
    01375             strncpy(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode) - 1);
    01376          }
    01377          if (user->amaflags) {
    01378             pvt->amaflags = user->amaflags;
    01379          }
    01380       }
    01381    }
    01382    return &pvt->options;
    01383 }
    01384
    01385 /**
    01386  * Call-back function to start PBX when OpenH323 ready to serve incoming call
    01387  *
    01388  * Returns 1 on success
    01389  */
    01390 static int answer_call(unsigned call_reference, const char *token)
    01391 {
    01392    struct oh323_pvt *pvt;
    01393    struct ast_channel *c = NULL;
    01394
    01395    if (h323debug)
    01396       ast_log(LOG_DEBUG, "Preparing Asterisk to answer for %s\n", token);
    01397
    01398    /* Find the call or allocate a private structure if call not found */
    01399    pvt = find_call_locked(call_reference, token);
    01400    if (!pvt) {
    01401       ast_log(LOG_ERROR, "Something is wrong: answer_call\n");
    01402       return 0;
    01403    }
    01404    /* allocate a channel and tell asterisk about it */
    01405    c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token);
    01406
    01407    /* And release when done */
    01408    ast_mutex_unlock(&pvt->lock);
    01409    if (!c) {
    01410       ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n");
    01411       return 0;
    01412    }
    01413    return 1;
    01414 }
    01415
    01416 /**
    01417  * Call-back function to establish an outgoing H.323 call
    01418  *
    01419  * Returns 1 on success
    01420  */
    01421 int setup_outgoing_call(call_details_t *cd)
    01422 {
    01423    /* Use argument here or free it immediately */
    01424    cleanup_call_details(cd);
    01425
    01426    return 1;
    01427 }
    01428
    01429 /**
    01430   *  Call-back function to signal asterisk that the channel is ringing
    01431   *  Returns nothing
    01432   */
    01433 void chan_ringing(unsigned call_reference, const char *token)
    01434 {
    01435    struct oh323_pvt *pvt;
    01436
    01437    if (h323debug)
    01438       ast_log(LOG_DEBUG, "Ringing on %s\n", token);
    01439
    01440    pvt = find_call_locked(call_reference, token);
    01441    if (!pvt) {
    01442       ast_log(LOG_ERROR, "Something is wrong: ringing\n");
    01443       return;
    01444    }
    01445    if (!pvt->owner) {
    01446       ast_mutex_unlock(&pvt->lock);
    01447       ast_log(LOG_ERROR, "Channel has no owner\n");
    01448       return;
    01449    }
    01450    if (update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING))
    01451       ast_mutex_unlock(&pvt->owner->lock);
    01452    ast_mutex_unlock(&pvt->lock);
    01453    return;
    01454 }
    01455
    01456 /**
    01457   * Call-back function to cleanup communication
    01458   * Returns nothing,
    01459   */
    01460 static void cleanup_connection(unsigned call_reference, const char *call_token)
    01461 {
    01462    struct oh323_pvt *pvt;
    01463
    01464    ast_log(LOG_DEBUG, "Cleaning connection to %s\n", call_token);
    01465
    01466    while (1) {
    01467       pvt = find_call_locked(call_reference, call_token);
    01468       if (!pvt) {
    01469          if (h323debug)
    01470             ast_log(LOG_DEBUG, "No connection for %s\n", call_token);
    01471          return;
    01472       }
    01473       if (!pvt->owner || !ast_mutex_trylock(&pvt->owner->lock))
    01474          break;
    01475 #if 1
    01476 #ifdef DEBUG_THREADS
    01477       ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s, locked at %ld/%d by %s (%s:%d)\n", call_token, pvt->owner->lock.thread, pvt->owner->lock.reentrancy, pvt->owner->lock.func, pvt->owner->lock.file, pvt->owner->lock.lineno);
    01478 #else
    01479       ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token);
    01480 #endif
    01481 #endif
    01482       ast_mutex_unlock(&pvt->lock);
    01483       usleep(1);
    01484    }
    01485    if (pvt->rtp) {
    01486       /* Immediately stop RTP */
    01487       ast_rtp_destroy(pvt->rtp);
    01488       pvt->rtp = NULL;
    01489    }
    01490    /* Free dsp used for in-band DTMF detection */
    01491    if (pvt->vad) {
    01492       ast_dsp_free(pvt->vad);
    01493       pvt->vad = NULL;
    01494    }
    01495    cleanup_call_details(&pvt->cd);
    01496    pvt->alreadygone = 1;
    01497    /* Send hangup */
    01498    if (pvt->owner) {
    01499       pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
    01500       ast_queue_hangup(pvt->owner);
    01501       ast_mutex_unlock(&pvt->owner->lock);
    01502    }
    01503    ast_mutex_unlock(&pvt->lock);
    01504    if (h323debug)
    01505       ast_log(LOG_DEBUG, "Connection to %s cleaned\n", call_token);
    01506    return;
    01507 }
    01508
    01509 static void hangup_connection(unsigned int call_reference, const char *token, int cause)
    01510 {
    01511    struct oh323_pvt *pvt;
    01512
    01513    ast_log(LOG_DEBUG, "Hanging up connection to %s with cause %d\n", token, cause);
    01514
    01515    pvt = find_call_locked(call_reference, token);
    01516    if (!pvt) {
    01517       return;
    01518    }
    01519    if (pvt->owner && !ast_mutex_trylock(&pvt->owner->lock)) {
    01520       pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
    01521       pvt->owner->hangupcause = pvt->hangupcause = cause;
    01522       ast_queue_hangup(pvt->owner);
    01523       ast_mutex_unlock(&pvt->owner->lock);
    01524    }
    01525    else {
    01526       pvt->needhangup = 1;
    01527       pvt->hangupcause = cause;
    01528       ast_log(LOG_DEBUG, "Hangup for %s is pending\n", token);
    01529    }
    01530    ast_mutex_unlock(&pvt->lock);
    01531 }
    01532
    01533 void set_dtmf_payload(unsigned call_reference, const char *token, int payload)
    01534 {
    01535    struct oh323_pvt *pvt;
    01536
    01537    if (h323debug)
    01538       ast_log(LOG_DEBUG, "Setting DTMF payload to %d on %s\n", payload, token);
    01539
    01540    pvt = find_call_locked(call_reference, token);
    01541    if (!pvt) {
    01542       return;
    01543    }
    01544    if (pvt->rtp) {
    01545       ast_rtp_set_rtpmap_type(pvt->rtp, payload, "audio", "telephone-event");
    01546    }
    01547    ast_mutex_unlock(&pvt->lock);
    01548    if (h323debug)
    01549       ast_log(LOG_DEBUG, "DTMF payload on %s set to %d\n", token, payload);
    01550 }
    01551
    01552 static void set_local_capabilities(unsigned call_reference, const char *token)
    01553 {
    01554    struct oh323_pvt *pvt;
    01555    int capability, dtmfmode;
    01556
    01557    if (h323debug)
    01558       ast_log(LOG_DEBUG, "Setting capabilities for connection %s\n", token);
    01559
    01560    pvt = find_call_locked(call_reference, token);
    01561    if (!pvt)
    01562       return;
    01563    capability = pvt->options.capability;
    01564    dtmfmode = pvt->options.dtmfmode;
    01565    ast_mutex_unlock(&pvt->lock);
    01566    h323_set_capabilities(token, capability, dtmfmode);
    01567
    01568    if (h323debug)
    01569       ast_log(LOG_DEBUG, "Capabilities for connection %s is set\n", token);
    01570 }
    01571
    01572 static void *do_monitor(void *data)
    01573 {
    01574    int res;
    01575    int reloading;
    01576    struct oh323_pvt *oh323 = NULL;
    01577
    01578    for(;;) {
    01579       /* Check for a reload request */
    01580       ast_mutex_lock(&h323_reload_lock);
    01581       reloading = h323_reloading;
    01582       h323_reloading = 0;
    01583       ast_mutex_unlock(&h323_reload_lock);
    01584       if (reloading) {
    01585          if (option_verbose > 0) {
    01586             ast_verbose(VERBOSE_PREFIX_1 "Reloading H.323\n");
    01587          }
    01588          h323_do_reload();
    01589       }
    01590       /* Check for interfaces needing to be killed */
    01591       ast_mutex_lock(&iflock);
    01592 restartsearch:
    01593       oh323 = iflist;
    01594       while(oh323) {
    01595          if (oh323->needdestroy) {
    01596             __oh323_destroy(oh323);
    01597             goto restartsearch;
    01598          }
    01599          oh323 = oh323->next;
    01600       }
    01601       ast_mutex_unlock(&iflock);
    01602       pthread_testcancel();
    01603       /* Wait for sched or io */
    01604       res = ast_sched_wait(sched);
    01605       if ((res < 0) || (res > 1000)) {
    01606          res = 1000;
    01607       }
    01608       res = ast_io_wait(io, res);
    01609       pthread_testcancel();
    01610       ast_mutex_lock(&monlock);
    01611       if (res >= 0) {
    01612          ast_sched_runq(sched);
    01613       }
    01614       ast_mutex_unlock(&monlock);
    01615    }
    01616    /* Never reached */
    01617    return NULL;
    01618 }
    01619
    01620 static int restart_monitor(void)
    01621 {
    01622    pthread_attr_t attr;
    01623    /* If we're supposed to be stopped -- stay stopped */
    01624    if (monitor_thread == AST_PTHREADT_STOP) {
    01625       return 0;
    01626    }
    01627    if (ast_mutex_lock(&monlock)) {
    01628       ast_log(LOG_WARNING, "Unable to lock monitor\n");
    01629       return -1;
    01630    }
    01631    if (monitor_thread == pthread_self()) {
    01632       ast_mutex_unlock(&monlock);
    01633       ast_log(LOG_WARNING, "Cannot kill myself\n");
    01634       return -1;
    01635    }
    01636    if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) {
    01637       /* Wake up the thread */
    01638       pthread_kill(monitor_thread, SIGURG);
    01639    } else {
    01640       pthread_attr_init(&attr);
    01641                 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    01642                 /* Start a new monitor */
    01643                 if (ast_pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
    01644                         ast_mutex_unlock(&monlock);
    01645                   pthread_attr_destroy(&attr);
    01646                         ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
    01647                         return -1;
    01648                 }
    01649       pthread_attr_destroy(&attr);
    01650
    01651    }
    01652    ast_mutex_unlock(&monlock);
    01653    return 0;
    01654 }
    01655
    01656 static int h323_do_trace(int fd, int argc, char *argv[])
    01657 {
    01658    if (argc != 3) {
    01659       return RESULT_SHOWUSAGE;
    01660    }
    01661    h323_debug(1, atoi(argv[2]));
    01662    ast_cli(fd, "H.323 trace set to level %s\n", argv[2]);
    01663    return RESULT_SUCCESS;
    01664 }
    01665
    01666 static int h323_no_trace(int fd, int argc, char *argv[])
    01667 {
    01668    if (argc != 3) {
    01669       return RESULT_SHOWUSAGE;
    01670    }
    01671    h323_debug(0,0);
    01672    ast_cli(fd, "H.323 trace disabled\n");
    01673    return RESULT_SUCCESS;
    01674 }
    01675
    01676 static int h323_do_debug(int fd, int argc, char *argv[])
    01677 {
    01678    if (argc != 2) {
    01679       return RESULT_SHOWUSAGE;
    01680    }
    01681    h323debug = 1;
    01682    ast_cli(fd, "H323 debug enabled\n");
    01683    return RESULT_SUCCESS;
    01684 }
    01685
    01686 static int h323_no_debug(int fd, int argc, char *argv[])
    01687 {
    01688    if (argc != 3) {
    01689       return RESULT_SHOWUSAGE;
    01690    }
    01691    h323debug = 0;
    01692    ast_cli(fd, "H323 Debug disabled\n");
    01693    return RESULT_SUCCESS;
    01694 }
    01695
    01696 static int h323_gk_cycle(int fd, int argc, char *argv[])
    01697 {
    01698 #if 0
    01699    if (argc != 3) {
    01700       return RESULT_SHOWUSAGE;
    01701    }
    01702    h323_gk_urq();
    01703
    01704    /* Possibly register with a GK */
    01705    if (!gatekeeper_disable) {
    01706       if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
    01707          ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
    01708       }
    01709    }
    01710 #endif
    01711    return RESULT_SUCCESS;
    01712 }
    01713
    01714 static int h323_ep_hangup(int fd, int argc, char *argv[])
    01715 {
    01716         if (argc != 3) {
    01717                 return RESULT_SHOWUSAGE;
    01718    }
    01719    if (h323_soft_hangup(argv[2])) {
    01720       ast_verbose(VERBOSE_PREFIX_3 "Hangup succeeded on %s\n", argv[2]);
    01721    } else {
    01722       ast_verbose(VERBOSE_PREFIX_3 "Hangup failed for %s\n", argv[2]);
    01723    }
    01724    return RESULT_SUCCESS;
    01725 }
    01726
    01727 static int h323_tokens_show(int fd, int argc, char *argv[])
    01728 {
    01729         if (argc != 3) {
    01730                 return RESULT_SHOWUSAGE;
    01731    }
    01732    h323_show_tokens();
    01733    return RESULT_SUCCESS;
    01734 }
    01735
    01736 static char trace_usage[] =
    01737 "Usage: h.323 trace <level num>\n"
    01738 "       Enables H.323 stack tracing for debugging purposes\n";
    01739
    01740 static char no_trace_usage[] =
    01741 "Usage: h.323 no trace\n"
    01742 "       Disables H.323 stack tracing for debugging purposes\n";
    01743
    01744 static char debug_usage[] =
    01745 "Usage: h.323 debug\n"
    01746 "       Enables H.323 debug output\n";
    01747
    01748 static char no_debug_usage[] =
    01749 "Usage: h.323 no debug\n"
    01750 "       Disables H.323 debug output\n";
    01751
    01752 static char show_codec_usage[] =
    01753 "Usage: h.323 show codec\n"
    01754 "       Shows all enabled codecs\n";
    01755
    01756 static char show_cycle_usage[] =
    01757 "Usage: h.323 gk cycle\n"
    01758 "       Manually re-register with the Gatekeper (Currently Disabled)\n";
    01759
    01760 static char show_hangup_usage[] =
    01761 "Usage: h.323 hangup <token>\n"
    01762 "       Manually try to hang up call identified by <token>\n";
    01763
    01764 static char show_tokens_usage[] =
    01765 "Usage: h.323 show tokens\n"
    01766 "       Print out all active call tokens\n";
    01767
    01768 static char h323_reload_usage[] =
    01769 "Usage: h323 reload\n"
    01770 "       Reloads H.323 configuration from sip.conf\n";
    01771
    01772 static struct ast_cli_entry  cli_trace =
    01773    { { "h.323", "trace", NULL }, h323_do_trace, "Enable H.323 Stack Tracing", trace_usage };
    01774 static struct ast_cli_entry  cli_no_trace =
    01775    { { "h.323", "no", "trace", NULL }, h323_no_trace, "Disable H.323 Stack Tracing", no_trace_usage };
    01776 static struct ast_cli_entry  cli_debug =
    01777    { { "h.323", "debug", NULL }, h323_do_debug, "Enable H.323 debug", debug_usage };
    01778 static struct ast_cli_entry  cli_no_debug =
    01779    { { "h.323", "no", "debug", NULL }, h323_no_debug, "Disable H.323 debug", no_debug_usage };
    01780 static struct ast_cli_entry  cli_show_codecs =
    01781    { { "h.323", "show", "codecs", NULL }, h323_show_codec, "Show enabled codecs", show_codec_usage };
    01782 static struct ast_cli_entry  cli_gk_cycle =
    01783    { { "h.323", "gk", "cycle", NULL }, h323_gk_cycle, "Manually re-register with the Gatekeper", show_cycle_usage };
    01784 static struct ast_cli_entry  cli_hangup_call =
    01785    { { "h.323", "hangup", NULL }, h323_ep_hangup, "Manually try to hang up a call", show_hangup_usage };
    01786 static struct ast_cli_entry  cli_show_tokens =
    01787    { { "h.323", "show", "tokens", NULL }, h323_tokens_show, "Show all active call tokens", show_tokens_usage };
    01788
    01789 static int update_common_options(struct ast_variable *v, struct call_options *options)
    01790 {
    01791    unsigned int format;
    01792    int tmp;
    01793
    01794    if (!strcasecmp(v->name, "allow")) {
    01795       format = ast_getformatbyname(v->value);
    01796       if (format < 1)
    01797          ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
    01798       else
    01799          options->capability |= format;
    01800    } else if (!strcasecmp(v->name, "disallow")) {
    01801       format = ast_getformatbyname(v->value);
    01802       if (format < 1)
    01803          ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
    01804       else
    01805          options->capability &= ~format;
    01806    } else if (!strcasecmp(v->name, "dtmfmode")) {
    01807       if (!strcasecmp(v->value, "inband")) {
    01808          options->dtmfmode = H323_DTMF_INBAND;
    01809       } else if (!strcasecmp(v->value, "rfc2833")) {
    01810          options->dtmfmode = H323_DTMF_RFC2833;
    01811       } else {
    01812          ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
    01813          options->dtmfmode = H323_DTMF_RFC2833;
    01814       }
    01815    } else if (!strcasecmp(v->name, "dtmfcodec")) {
    01816       tmp = atoi(v->value);
    01817       if (tmp < 96)
    01818          ast_log(LOG_WARNING, "Invalid global dtmfcodec value %s\n", v->value);
    01819       else
    01820          options->dtmfcodec = tmp;
    01821    } else if (!strcasecmp(v->name, "bridge")) {
    01822       options->bridge = ast_true(v->value);
    01823    } else if (!strcasecmp(v->name, "nat")) {
    01824       options->nat = ast_true(v->value);
    01825    } else if (!strcasecmp(v->name, "noFastStart")) {
    01826       options->noFastStart = ast_true(v->value);
    01827    } else if (!strcasecmp(v->name, "noH245Tunneling")) {
    01828       options->noH245Tunneling = ast_true(v->value);
    01829    } else if (!strcasecmp(v->name, "noSilenceSuppression")) {
    01830       options->noSilenceSuppression = ast_true(v->value);
    01831    } else if (!strcasecmp(v->name, "progress_setup")) {
    01832       tmp = atoi(v->value);
    01833       if ((tmp != 0) && (tmp != 1) && (tmp != 3) && (tmp != 8)) {
    01834          ast_log(LOG_WARNING, "Invalid value %d for progress_setup at line %d, assuming 0\n", tmp, v->lineno);
    01835          tmp = 0;
    01836       }
    01837       options->progress_setup = tmp;
    01838    } else if (!strcasecmp(v->name, "progress_alert")) {
    01839       tmp = atoi(v->value);
    01840       if ((tmp != 0) && (tmp != 8)) {
    01841          ast_log(LOG_WARNING, "Invalud value %d for progress_alert at line %d, assuming 0\n", tmp, v->lineno);
    01842          tmp = 0;
    01843       }
    01844       options->progress_alert = tmp;
    01845    } else if (!strcasecmp(v->name, "progress_audio")) {
    01846       options->progress_audio = ast_true(v->value);
    01847    } else
    01848       return 1;
    01849
    01850    return 0;
    01851 }
    01852
    01853 static struct oh323_alias *build_alias(char *name, struct ast_variable *v)
    01854 {
    01855    struct oh323_alias *alias;
    01856
    01857    alias = (struct oh323_alias *)malloc(sizeof(struct oh323_alias));
    01858    if (alias) {
    01859       memset(alias, 0, sizeof(struct oh323_alias));
    01860       strncpy(alias->name, name, sizeof(alias->name) - 1);
    01861       while (v) {
    01862          if (!strcasecmp(v->name, "e164")) {
    01863             strncpy(alias->e164,  v->value, sizeof(alias->e164) - 1);
    01864          } else if (!strcasecmp(v->name, "prefix")) {
    01865             strncpy(alias->prefix,  v->value, sizeof(alias->prefix) - 1);
    01866          } else if (!strcasecmp(v->name, "context")) {
    01867             strncpy(alias->context,  v->value, sizeof(alias->context) - 1);
    01868          } else if (!strcasecmp(v->name, "secret")) {
    01869             strncpy(alias->secret,  v->value, sizeof(alias->secret) - 1);
    01870          } else {
    01871             if (strcasecmp(v->value, "h323")) {
    01872                ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->value);
    01873             }
    01874          }
    01875          v = v->next;
    01876       }
    01877    }
    01878    return alias;
    01879 }
    01880
    01881 static struct oh323_user *build_user(char *name, struct ast_variable *v)
    01882 {
    01883    struct oh323_user *user;
    01884    int format;
    01885
    01886    user = (struct oh323_user *)malloc(sizeof(struct oh323_user));
    01887    if (user) {
    01888       memset(user, 0, sizeof(struct oh323_user));
    01889       strncpy(user->name, name, sizeof(user->name) - 1);
    01890       memcpy(&user->options, &global_options, sizeof(user->options));
    01891       /* Set default context */
    01892       strncpy(user->context, default_context, sizeof(user->context) - 1);
    01893       while(v) {
    01894          if (!strcasecmp(v->name, "context")) {
    01895             strncpy(user->context, v->value, sizeof(user->context) - 1);
    01896          } else if (!update_common_options(v, &user->options)) {
    01897             /* dummy */
    01898          } else if (!strcasecmp(v->name, "secret")) {
    01899             strncpy(user->secret, v->value, sizeof(user->secret) - 1);
    01900          } else if (!strcasecmp(v->name, "callerid")) {
    01901             strncpy(user->callerid, v->value, sizeof(user->callerid) - 1);
    01902          } else if (!strcasecmp(v->name, "accountcode")) {
    01903             strncpy(user->accountcode, v->value, sizeof(user->accountcode) - 1);
    01904          } else if (!strcasecmp(v->name, "host")) {
    01905             if (!strcasecmp(v->value, "dynamic")) {
    01906                ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n");
    01907                free(user);
    01908                return NULL;
    01909             } else if (ast_get_ip(&user->addr, v->value)) {
    01910                free(user);
    01911                return NULL;
    01912             }
    01913             /* Let us know we need to use ip authentication */
    01914             user->host = 1;
    01915          } else if (!strcasecmp(v->name, "amaflags")) {
    01916             format = ast_cdr_amaflags2int(v->value);
    01917             if (format < 0) {
    01918                ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
    01919             } else {
    01920                user->amaflags = format;
    01921             }
    01922          }
    01923          v = v->next;
    01924       }
    01925    }
    01926    return user;
    01927 }
    01928
    01929 static struct oh323_peer *build_peer(char *name, struct ast_variable *v)
    01930 {
    01931    struct oh323_peer *peer;
    01932    struct oh323_peer *prev;
    01933    struct ast_ha *oldha = NULL;
    01934    int found=0;
    01935
    01936    prev = NULL;
    01937    ast_mutex_lock(&peerl.lock);
    01938    peer = peerl.peers;
    01939
    01940    while(peer) {
    01941       if (!strcasecmp(peer->name, name)) {
    01942          break;
    01943       }
    01944       prev = peer;
    01945       peer = peer->next;
    01946    }
    01947
    01948    if (peer) {
    01949       found++;
    01950       /* Already in the list, remove it and it will be added back (or FREE'd) */
    01951       if (prev) {
    01952          prev->next = peer->next;
    01953       } else {
    01954          peerl.peers = peer->next;
    01955       }
    01956       ast_mutex_unlock(&peerl.lock);
    01957    } else {
    01958       ast_mutex_unlock(&peerl.lock);
    01959       peer = (struct oh323_peer*)malloc(sizeof(struct oh323_peer));
    01960       if (peer)
    01961          memset(peer, 0, sizeof(struct oh323_peer));
    01962    }
    01963    if (peer) {
    01964       if (!found) {
    01965          strncpy(peer->name, name, sizeof(peer->name) - 1);
    01966          peer->addr.sin_port = htons(h323_signalling_port);
    01967          peer->addr.sin_family = AF_INET;
    01968       }
    01969       oldha = peer->ha;
    01970       peer->ha = NULL;
    01971       peer->addr.sin_family = AF_INET;
    01972       memcpy(&peer->options, &global_options, sizeof(peer->options));
    01973
    01974       while(v) {
    01975          if (!update_common_options(v, &peer->options)) {
    01976             /* dummy */
    01977          } else if (!strcasecmp(v->name, "host")) {
    01978             if (!strcasecmp(v->value, "dynamic")) {
    01979                ast_log(LOG_ERROR, "Dynamic host configuration not implemented.\n");
    01980                free(peer);
    01981                return NULL;
    01982             }
    01983             if (ast_get_ip(&peer->addr, v->value)) {
    01984                   ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value);
    01985                   free(peer);
    01986                   return NULL;
    01987             }
    01988          } else if (!strcasecmp(v->name, "port")) {
    01989             peer->addr.sin_port = htons(atoi(v->value));
    01990          }
    01991          v=v->next;
    01992       }
    01993    }
    01994    return peer;
    01995 }
    01996
    01997 int reload_config(void)
    01998 {
    01999    int format;
    02000    struct ast_config *cfg;
    02001    struct ast_variable *v;
    02002    struct oh323_peer *peer   = NULL;
    02003    struct oh323_user *user   = NULL;
    02004    struct oh323_alias *alias = NULL;
    02005    struct ast_hostent ahp; struct hostent *hp;
    02006    char *cat;
    02007       char *utype;
    02008
    02009    cfg = ast_config_load(config);
    02010
    02011    /* We *must* have a config file otherwise stop immediately */
    02012    if (!cfg) {
    02013       ast_log(LOG_NOTICE, "Unable to load config %s, H.323 disabled\n", config);
    02014       return 1;
    02015    }
    02016
    02017        /* fire up the H.323 Endpoint */
    02018    if (!h323_end_point_exist()) {
    02019           h323_end_point_create();
    02020    }
    02021    h323debug = 0;
    02022    memset(&bindaddr, 0, sizeof(bindaddr));
    02023    memset(&global_options, 0, sizeof(global_options));
    02024    global_options.dtmfcodec = 101;
    02025    global_options.dtmfmode = H323_DTMF_RFC2833;
    02026    global_options.capability = AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_H261;
    02027    global_options.bridge = 1;    /* Do native bridging by default */
    02028    v = ast_variable_browse(cfg, "general");
    02029    while(v) {
    02030       /* Create the interface list */
    02031       if (!strcasecmp(v->name, "port")) {
    02032          h323_signalling_port = (int)strtol(v->value, NULL, 10);
    02033       } else if (!strcasecmp(v->name, "bindaddr")) {
    02034          if (!(hp = ast_gethostbyname(v->value, &ahp))) {
    02035             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
    02036          } else {
    02037             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
    02038          }
    02039       } else if (!strcasecmp(v->name, "tos")) {
    02040          if (sscanf(v->value, "%30d", &format)) {
    02041             tos = format & 0xff;
    02042          } else if (!strcasecmp(v->value, "lowdelay")) {
    02043             tos = IPTOS_LOWDELAY;
    02044          } else if (!strcasecmp(v->value, "throughput")) {
    02045             tos = IPTOS_THROUGHPUT;
    02046          } else if (!strcasecmp(v->value, "reliability")) {
    02047             tos = IPTOS_RELIABILITY;
    02048          } else if (!strcasecmp(v->value, "mincost")) {
    02049             tos = IPTOS_MINCOST;
    02050          } else if (!strcasecmp(v->value, "none")) {
    02051             tos = 0;
    02052          } else {
    02053             ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
    02054          }
    02055       } else if (!strcasecmp(v->name, "gatekeeper")) {
    02056          if (!strcasecmp(v->value, "DISABLE")) {
    02057             gatekeeper_disable = 1;
    02058             usingGk = 0;
    02059          } else if (!strcasecmp(v->value, "DISCOVER")) {
    02060             gatekeeper_disable = 0;
    02061             gatekeeper_discover = 1;
    02062             usingGk = 1;
    02063          } else {
    02064             gatekeeper_disable = 0;
    02065             usingGk = 1;
    02066             strncpy(gatekeeper, v->value, sizeof(gatekeeper) - 1);
    02067          }
    02068       } else if (!strcasecmp(v->name, "secret")) {
    02069          strncpy(secret, v->value, sizeof(secret) - 1);
    02070       } else if (!strcasecmp(v->name, "AllowGKRouted")) {
    02071          gkroute = ast_true(v->value);
    02072       } else if (!strcasecmp(v->name, "context")) {
    02073          strncpy(default_context, v->value, sizeof(default_context) - 1);
    02074          ast_verbose(VERBOSE_PREFIX_2 "Setting default context to %s\n", default_context);
    02075       } else if (!strcasecmp(v->name, "UserByAlias")) {
    02076          userbyalias = ast_true(v->value);
    02077       } else if (!update_common_options(v, &global_options)) {
    02078          /* dummy */
    02079       }
    02080       v = v->next;
    02081    }
    02082
    02083    cat = ast_category_browse(cfg, NULL);
    02084    while(cat) {
    02085       if (strcasecmp(cat, "general")) {
    02086          utype = ast_variable_retrieve(cfg, cat, "type");
    02087          if (utype) {
    02088             if (!strcasecmp(utype, "user")) {
    02089                user = build_user(cat, ast_variable_browse(cfg, cat));
    02090                if (user) {
    02091                   ast_mutex_lock(&userl.lock);
    02092                   user->next = userl.users;
    02093                   userl.users = user;
    02094                   ast_mutex_unlock(&userl.lock);
    02095                }
    02096             }  else if (!strcasecmp(utype, "peer")) {
    02097                peer = build_peer(cat, ast_variable_browse(cfg, cat));
    02098                if (peer) {
    02099                   ast_mutex_lock(&peerl.lock);
    02100                   peer->next = peerl.peers;
    02101                   peerl.peers = peer;
    02102                   ast_mutex_unlock(&peerl.lock);
    02103                }
    02104             }  else if (!strcasecmp(utype, "friend")) {
    02105                user = build_user(cat, ast_variable_browse(cfg, cat));
    02106                peer = build_peer(cat, ast_variable_browse(cfg, cat));
    02107                if (user) {
    02108                   ast_mutex_lock(&userl.lock);
    02109                   user->next = userl.users;
    02110                   userl.users = user;
    02111                   ast_mutex_unlock(&userl.lock);
    02112                }
    02113                if (peer) {
    02114                   ast_mutex_lock(&peerl.lock);
    02115                   peer->next = peerl.peers;
    02116                   peerl.peers = peer;
    02117                   ast_mutex_unlock(&peerl.lock);
    02118                }
    02119             }  else if (!strcasecmp(utype, "h323") || !strcasecmp(utype, "alias")) {
    02120                alias = build_alias(cat, ast_variable_browse(cfg, cat));
    02121                if (alias) {
    02122                   ast_mutex_lock(&aliasl.lock);
    02123                   alias->next = aliasl.aliases;
    02124                   aliasl.aliases = alias;
    02125                   ast_mutex_unlock(&aliasl.lock);
    02126                }
    02127             } else {
    02128                ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config);
    02129             }
    02130          } else {
    02131             ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
    02132          }
    02133       }
    02134       cat = ast_category_browse(cfg, cat);
    02135    }
    02136    ast_config_destroy(cfg);
    02137
    02138    /* Register our H.323 aliases if any*/
    02139    while (alias) {
    02140       if (h323_set_alias(alias)) {
    02141          ast_log(LOG_ERROR, "Alias %s rejected by endpoint\n", alias->name);
    02142          return -1;
    02143       }
    02144       alias = alias->next;
    02145    }
    02146
    02147    return 0;
    02148 }
    02149
    02150 void delete_users(void)
    02151 {
    02152    struct oh323_user *user, *userlast;
    02153    struct oh323_peer *peer;
    02154
    02155    /* Delete all users */
    02156    ast_mutex_lock(&userl.lock);
    02157    for (user=userl.users;user;) {
    02158       userlast = user;
    02159       user=user->next;
    02160       free(userlast);
    02161    }
    02162    userl.users=NULL;
    02163    ast_mutex_unlock(&userl.lock);
    02164    ast_mutex_lock(&peerl.lock);
    02165    for (peer=peerl.peers;peer;) {
    02166       /* Assume all will be deleted, and we'll find out for sure later */
    02167       peer->delme = 1;
    02168       peer = peer->next;
    02169    }
    02170    ast_mutex_unlock(&peerl.lock);
    02171 }
    02172
    02173 void delete_aliases(void)
    02174 {
    02175    struct oh323_alias *alias, *aliaslast;
    02176
    02177    /* Delete all users */
    02178    ast_mutex_lock(&aliasl.lock);
    02179    for (alias=aliasl.aliases;alias;) {
    02180       aliaslast = alias;
    02181       alias=alias->next;
    02182       free(aliaslast);
    02183    }
    02184    aliasl.aliases=NULL;
    02185    ast_mutex_unlock(&aliasl.lock);
    02186 }
    02187
    02188 void prune_peers(void)
    02189 {
    02190    /* Prune peers who still are supposed to be deleted */
    02191    struct oh323_peer *peer, *peerlast, *peernext;
    02192    ast_mutex_lock(&peerl.lock);
    02193    peerlast = NULL;
    02194    for (peer=peerl.peers;peer;) {
    02195       peernext = peer->next;
    02196       if (peer->delme) {
    02197          free(peer);
    02198          if (peerlast) {
    02199             peerlast->next = peernext;
    02200          } else {
    02201             peerl.peers = peernext;
    02202          }
    02203       } else {
    02204          peerlast = peer;
    02205       }
    02206       peer = peernext;
    02207    }
    02208    ast_mutex_unlock(&peerl.lock);
    02209 }
    02210
    02211 static int h323_reload(int fd, int argc, char *argv[])
    02212 {
    02213    ast_mutex_lock(&h323_reload_lock);
    02214    if (h323_reloading) {
    02215       ast_verbose("Previous H.323 reload not yet done\n");
    02216    } else {
    02217       h323_reloading = 1;
    02218    }
    02219    ast_mutex_unlock(&h323_reload_lock);
    02220    restart_monitor();
    02221    return 0;
    02222 }
    02223
    02224 static int h323_do_reload(void)
    02225 {
    02226    delete_users();
    02227    delete_aliases();
    02228    prune_peers();
    02229    reload_config();
    02230    restart_monitor();
    02231    return 0;
    02232 }
    02233
    02234 int reload(void)
    02235 {
    02236    return h323_reload(0, 0, NULL);
    02237 }
    02238
    02239 static struct ast_cli_entry  cli_h323_reload =
    02240    { { "h.323", "reload", NULL }, h323_reload, "Reload H.323 configuration", h323_reload_usage };
    02241
    02242 static struct ast_rtp *oh323_get_rtp_peer(struct ast_channel *chan)
    02243 {
    02244    struct oh323_pvt *pvt;
    02245    pvt = (struct oh323_pvt *) chan->tech_pvt;
    02246    if (pvt && pvt->rtp && pvt->options.bridge) {
    02247       return pvt->rtp;
    02248    }
    02249    return NULL;
    02250 }
    02251
    02252 static struct ast_rtp *oh323_get_vrtp_peer(struct ast_channel *chan)
    02253 {
    02254    return NULL;
    02255 }
    02256
    02257 static char *convertcap(int cap)
    02258 {
    02259    switch (cap) {
    02260    case AST_FORMAT_G723_1:
    02261       return "G.723";
    02262    case AST_FORMAT_GSM:
    02263       return "GSM";
    02264    case AST_FORMAT_ULAW:
    02265       return "ULAW";
    02266    case AST_FORMAT_ALAW:
    02267       return "ALAW";
    02268    case AST_FORMAT_ADPCM:
    02269       return "G.728";
    02270    case AST_FORMAT_G729A:
    02271       return "G.729";
    02272    case AST_FORMAT_SPEEX:
    02273       return "SPEEX";
    02274    case AST_FORMAT_ILBC:
    02275       return "ILBC";
    02276    default:
    02277       ast_log(LOG_NOTICE, "Don't know how to deal with mode %d\n", cap);
    02278       return NULL;
    02279    }
    02280 }
    02281
    02282 static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
    02283 {
    02284    /* XXX Deal with Video */
    02285    struct oh323_pvt *pvt;
    02286    struct sockaddr_in them;
    02287    struct sockaddr_in us;
    02288    char *mode;
    02289    char iabuf[INET_ADDRSTRLEN];
    02290
    02291    if (!rtp) {
    02292       return 0;
    02293    }
    02294
    02295    mode = convertcap(chan->writeformat);
    02296    pvt = (struct oh323_pvt *) chan->tech_pvt;
    02297    if (!pvt) {
    02298       ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
    02299       return -1;
    02300    }
    02301    ast_rtp_get_peer(rtp, &them);
    02302    ast_rtp_get_us(rtp, &us);
    02303    h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(iabuf, sizeof(iabuf), them.sin_addr), mode);
    02304    return 0;
    02305 }
    02306
    02307 static struct ast_rtp_protocol oh323_rtp = {
    02308    .type = type,
    02309    .get_rtp_info = oh323_get_rtp_peer,
    02310    .get_vrtp_info = oh323_get_vrtp_peer,
    02311    .set_rtp_peer = oh323_set_rtp_peer,
    02312 };
    02313
    02314 int load_module()
    02315 {
    02316    int res;
    02317    ast_mutex_init(&userl.lock);
    02318    ast_mutex_init(&peerl.lock);
    02319    ast_mutex_init(&aliasl.lock);
    02320    sched = sched_context_create();
    02321    if (!sched) {
    02322       ast_log(LOG_WARNING, "Unable to create schedule context\n");
    02323    }
    02324    io = io_context_create();
    02325    if (!io) {
    02326       ast_log(LOG_WARNING, "Unable to create I/O context\n");
    02327    }
    02328    res = reload_config();
    02329    if (res) {
    02330       return 0;
    02331    } else {
    02332       /* Make sure we can register our channel type */
    02333       if (ast_channel_register(&oh323_tech)) {
    02334          ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
    02335          h323_end_process();
    02336          return -1;
    02337       }
    02338       ast_cli_register(&cli_debug);
    02339       ast_cli_register(&cli_no_debug);
    02340       ast_cli_register(&cli_trace);
    02341       ast_cli_register(&cli_no_trace);
    02342       ast_cli_register(&cli_show_codecs);
    02343       ast_cli_register(&cli_gk_cycle);
    02344       ast_cli_register(&cli_hangup_call);
    02345       ast_cli_register(&cli_show_tokens);
    02346       ast_cli_register(&cli_h323_reload);
    02347
    02348       ast_rtp_proto_register(&oh323_rtp);
    02349
    02350       /* Register our callback functions */
    02351       h323_callback_register(setup_incoming_call,
    02352                   setup_outgoing_call,
    02353                   external_rtp_create,
    02354                   setup_rtp_connection,
    02355                   cleanup_connection,
    02356                   chan_ringing,
    02357                   connection_made,
    02358                   send_digit,
    02359                   answer_call,
    02360                   progress,
    02361                   set_dtmf_payload,
    02362                   hangup_connection,
    02363                   set_local_capabilities);
    02364       /* start the h.323 listener */
    02365       if (h323_start_listener(h323_signalling_port, bindaddr)) {
    02366          ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
    02367          return -1;
    02368       }
    02369       /* Possibly register with a GK */
    02370       if (!gatekeeper_disable) {
    02371          if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
    02372             ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
    02373             return 0;
    02374          }
    02375       }
    02376       /* And start the monitor for the first time */
    02377       restart_monitor();
    02378    }
    02379    return res;
    02380 }
    02381
    02382 int unload_module()
    02383 {
    02384    struct oh323_pvt *p, *pl;
    02385
    02386    /* unregister commands */
    02387    ast_cli_unregister(&cli_debug);
    02388    ast_cli_unregister(&cli_no_debug);
    02389    ast_cli_unregister(&cli_trace);
    02390    ast_cli_unregister(&cli_no_trace);
    02391    ast_cli_unregister(&cli_show_codecs);
    02392    ast_cli_unregister(&cli_gk_cycle);
    02393    ast_cli_unregister(&cli_hangup_call);
    02394    ast_cli_unregister(&cli_show_tokens);
    02395    ast_cli_unregister(&cli_h323_reload);
    02396    ast_rtp_proto_unregister(&oh323_rtp);
    02397    ast_channel_unregister(&oh323_tech);
    02398
    02399    if (!ast_mutex_lock(&iflock)) {
    02400       /* hangup all interfaces if they have an owner */
    02401       p = iflist;
    02402       while(p) {
    02403          if (p->owner) {
    02404             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
    02405          }
    02406          p = p->next;
    02407       }
    02408       iflist = NULL;
    02409       ast_mutex_unlock(&iflock);
    02410    } else {
    02411       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
    02412       return -1;
    02413    }
    02414    if (!ast_mutex_lock(&monlock)) {
    02415       if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
    02416          /* this causes a seg, anyone know why? */
    02417          pthread_cancel(monitor_thread);
    02418          pthread_kill(monitor_thread, SIGURG);
    02419          pthread_join(monitor_thread, NULL);
    02420       }
    02421       monitor_thread = AST_PTHREADT_STOP;
    02422       ast_mutex_unlock(&monlock);
    02423    } else {
    02424       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
    02425       return -1;
    02426    }
    02427    if (!ast_mutex_lock(&iflock)) {
    02428       /* destroy all the interfaces and free their memory */
    02429       p = iflist;
    02430       while(p) {
    02431          pl = p;
    02432          p = p->next;
    02433          /* free associated memory */
    02434          ast_mutex_destroy(&pl->lock);
    02435          free(pl);
    02436       }
    02437       iflist = NULL;
    02438       ast_mutex_unlock(&iflock);
    02439    } else {
    02440       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
    02441       return -1;
    02442    }
    02443    h323_gk_urq();
    02444    h323_end_process();
    02445    io_context_destroy(io);
    02446    sched_context_destroy(sched);
    02447    delete_users();
    02448    delete_aliases();
    02449    prune_peers();
    02450    ast_mutex_destroy(&aliasl.lock);
    02451    ast_mutex_destroy(&userl.lock);
    02452    ast_mutex_destroy(&peerl.lock);
    02453    return 0;
    02454 }
    02455
    02456 int usecount()
    02457 {
    02458    return usecnt;
    02459 }
    02460
    02461 char *description()
    02462 {
    02463    return (char *) desc;
    02464 }
    02465
    02466 char *key()
    02467 {
    02468    return ASTERISK_GPL_KEY;
    02469 }