[asterisk-commits] pcadach: branch pcadach/chan_h323-live r41358 -
/team/pcadach/chan_h323-live/...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Wed Aug 30 08:30:41 MST 2006
Author: pcadach
Date: Wed Aug 30 10:30:41 2006
New Revision: 41358
URL: http://svn.digium.com/view/asterisk?rev=41358&view=rev
Log:
Preliminary realtime support for chan_h323
Modified:
team/pcadach/chan_h323-live/channels/chan_h323.c
Modified: team/pcadach/chan_h323-live/channels/chan_h323.c
URL: http://svn.digium.com/view/asterisk/team/pcadach/chan_h323-live/channels/chan_h323.c?rev=41358&r1=41357&r2=41358&view=diff
==============================================================================
--- team/pcadach/chan_h323-live/channels/chan_h323.c (original)
+++ team/pcadach/chan_h323-live/channels/chan_h323.c Wed Aug 30 10:30:41 2006
@@ -971,979 +971,40 @@
}
}
-static int oh323_addrcmp_str(struct in_addr inaddr, char *addr)
-{
- return strcmp(ast_inet_ntoa(inaddr), addr);
-}
-
-static struct oh323_user *find_user(const call_details_t *cd, int realtime)
-{
- struct oh323_user *u;
-
- if (userbyalias)
- u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases);
- else
- u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str);
-
-#if 0 /* XXX REALTIME XXX*/
- if (!u && realtime)
- u = realtime_user(cd);
-#endif
-
- if (!u && h323debug)
- ast_log(LOG_DEBUG, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp);
-
- return u;
-}
-
-static int oh323_addrcmp(struct sockaddr_in addr, struct sockaddr_in *sin)
-{
- int res;
-
- if (!sin)
- res = -1;
- else
- res = inaddrcmp(&addr , sin);
-
- return res;
-}
-
-static struct oh323_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime)
-{
- struct oh323_peer *p = NULL;
-
- if (peer)
- p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
- else
- p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
-
-#if 0 /* XXX REALTIME XXX */
- if (!p && realtime)
- p = realtime_peer(peer, sin);
-#endif
-
- if (!p && h323debug)
- ast_log(LOG_DEBUG, "Could not find peer by name %s or address %s\n", (peer ? peer : "<NONE>"), (sin ? ast_inet_ntoa(sin->sin_addr) : "<NONE>"));
-
- return p;
-}
-
-static int create_addr(struct oh323_pvt *pvt, char *opeer)
-{
- struct hostent *hp;
- struct ast_hostent ahp;
- struct oh323_peer *p;
- int portno;
+static struct oh323_alias *build_alias(char *name, struct ast_variable *v)
+{
+ struct oh323_alias *alias;
int found = 0;
- char *port;
- char *hostn;
- char peer[256] = "";
-
- strncpy(peer, opeer, sizeof(peer) - 1);
- port = strchr(peer, ':');
- if (port) {
- *port = '\0';
- port++;
- }
- pvt->sa.sin_family = AF_INET;
- p = find_peer(peer, NULL, 0);
- if (p) {
+
+ alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&aliasl, name, name, 0, 0, strcasecmp);
+
+ if (alias)
found++;
- memcpy(&pvt->options, &p->options, sizeof(pvt->options));
- pvt->jointcapability = pvt->options.capability;
- if (pvt->rtp) {
- ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat);
- ast_rtp_setnat(pvt->rtp, pvt->options.nat);
- }
- if (pvt->options.dtmfmode) {
- if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
- pvt->nonCodecCapability |= AST_RTP_DTMF;
- } else {
- pvt->nonCodecCapability &= ~AST_RTP_DTMF;
- }
- }
- if (p->addr.sin_addr.s_addr) {
- pvt->sa.sin_addr = p->addr.sin_addr;
- pvt->sa.sin_port = p->addr.sin_port;
- }
- ASTOBJ_UNREF(p, oh323_destroy_peer);
- }
- if (!p && !found) {
- hostn = peer;
- if (port) {
- portno = atoi(port);
+ else {
+ if (!(alias = (struct oh323_alias *)calloc(1, sizeof(*alias))))
+ return NULL;
+ ASTOBJ_INIT(alias);
+ }
+ if (!found && name)
+ strncpy(alias->name, name, sizeof(alias->name) - 1);
+ for (; v; v = v->next) {
+ if (!strcasecmp(v->name, "e164")) {
+ strncpy(alias->e164, v->value, sizeof(alias->e164) - 1);
+ } else if (!strcasecmp(v->name, "prefix")) {
+ strncpy(alias->prefix, v->value, sizeof(alias->prefix) - 1);
+ } else if (!strcasecmp(v->name, "context")) {
+ strncpy(alias->context, v->value, sizeof(alias->context) - 1);
+ } else if (!strcasecmp(v->name, "secret")) {
+ strncpy(alias->secret, v->value, sizeof(alias->secret) - 1);
} else {
- portno = h323_signalling_port;
- }
- hp = ast_gethostbyname(hostn, &ahp);
- if (hp) {
- memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
- pvt->sa.sin_port = htons(portno);
- /* Look peer by address */
- p = find_peer(NULL, &pvt->sa, 0);
- memcpy(&pvt->options, (p ? &p->options : &global_options), sizeof(pvt->options));
- pvt->jointcapability = pvt->options.capability;
- if (p) {
- ASTOBJ_UNREF(p, oh323_destroy_peer);
- }
- if (pvt->rtp) {
- ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat);
- ast_rtp_setnat(pvt->rtp, pvt->options.nat);
- }
- if (pvt->options.dtmfmode) {
- if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
- pvt->nonCodecCapability |= AST_RTP_DTMF;
- } else {
- pvt->nonCodecCapability &= ~AST_RTP_DTMF;
- }
- }
- return 0;
- } else {
- ast_log(LOG_WARNING, "No such host: %s\n", peer);
- return -1;
- }
- } else if (!p) {
- return -1;
- } else {
- return 0;
- }
-}
-static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause)
-{
- int oldformat;
- struct oh323_pvt *pvt;
- struct ast_channel *tmpc = NULL;
- char *dest = (char *)data;
- char *ext, *host;
- char *h323id = NULL;
- char tmp[256], tmp1[256];
-
- ast_log(LOG_DEBUG, "type=%s, format=%d, data=%s.\n", type, format, (char *)data);
- pvt = oh323_alloc(0);
- if (!pvt) {
- ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data);
- return NULL;
- }
- oldformat = format;
- format &= ((AST_FORMAT_MAX_AUDIO << 1) - 1);
- if (!format) {
- ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
- oh323_destroy(pvt);
- return NULL;
- }
- strncpy(tmp, dest, sizeof(tmp) - 1);
- host = strchr(tmp, '@');
- if (host) {
- *host = '\0';
- host++;
- ext = tmp;
- } else {
- host = tmp;
- ext = NULL;
- }
- strtok_r(host, "/", &(h323id));
- if (!ast_strlen_zero(h323id)) {
- h323_set_id(h323id);
- }
- if (ext) {
- strncpy(pvt->exten, ext, sizeof(pvt->exten) - 1);
- }
- ast_log(LOG_DEBUG, "Extension: %s Host: %s\n", pvt->exten, host);
- if (!usingGk) {
- if (create_addr(pvt, host)) {
- oh323_destroy(pvt);
- return NULL;
- }
- }
- else {
- memcpy(&pvt->options, &global_options, sizeof(pvt->options));
- pvt->jointcapability = pvt->options.capability;
- if (pvt->rtp) {
- ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat);
- ast_rtp_setnat(pvt->rtp, pvt->options.nat);
- }
- if (pvt->options.dtmfmode) {
- if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
- pvt->nonCodecCapability |= AST_RTP_DTMF;
- } else {
- pvt->nonCodecCapability &= ~AST_RTP_DTMF;
- }
- }
- }
-
- ast_mutex_lock(&caplock);
- /* Generate unique channel identifier */
- snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
- tmp1[sizeof(tmp1)-1] = '\0';
- ast_mutex_unlock(&caplock);
-
- ast_mutex_lock(&pvt->lock);
- tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1);
- ast_mutex_unlock(&pvt->lock);
- if (!tmpc) {
- oh323_destroy(pvt);
- }
- ast_update_use_count();
- restart_monitor();
- return tmpc;
-}
-
-/** Find a call by alias */
-static struct oh323_alias *find_alias(const char *source_aliases)
-{
- struct oh323_alias *a;
-
- a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
-
-#if 0 /* XXX REALTIME XXX */
- if (!a && realtime)
- a = realtime_alias(source_aliases);
-#endif
-
- return a;
-}
-
-/**
- * Callback for sending digits from H.323 up to asterisk
- *
- */
-static int send_digit(unsigned call_reference, char digit, const char *token)
-{
- struct oh323_pvt *pvt;
- int res;
-
- if (digit == ' ') /* DTMF tone update -- ignore */
- return 0;
- ast_log(LOG_DEBUG, "Received Digit: %c\n", digit);
- pvt = find_call_locked(call_reference, token);
- if (!pvt) {
- ast_log(LOG_ERROR, "Private structure not found in send_digit.\n");
- return -1;
- }
- if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
- if (digit == '!')
- res = ast_queue_control(pvt->owner, AST_CONTROL_FLASH);
- else {
- struct ast_frame f = {
- .frametype = AST_FRAME_DTMF,
- .subclass = digit,
- .samples = 800,
- .src = "SEND_DIGIT",
- };
- res = ast_queue_frame(pvt->owner, &f);
- }
- ast_channel_unlock(pvt->owner);
- } else {
- if (digit == '!')
- pvt->newcontrol = AST_CONTROL_FLASH;
- else
- pvt->newdigit = digit;
- res = 0;
- }
- ast_mutex_unlock(&pvt->lock);
- return res;
-}
-
-/**
- * Callback function used to inform the H.323 stack of the local rtp ip/port details
- *
- * Returns the local RTP information
- */
-static struct rtp_info *external_rtp_create(unsigned call_reference, const char * token)
-{
- struct oh323_pvt *pvt;
- struct sockaddr_in us;
- struct rtp_info *info;
-
- info = (struct rtp_info *)malloc(sizeof(struct rtp_info));
- if (!info) {
- ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
- return NULL;
- }
- pvt = find_call_locked(call_reference, token);
- if (!pvt) {
- free(info);
- ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
- return NULL;
- }
- /* figure out our local RTP port and tell the H.323 stack about it */
- ast_rtp_get_us(pvt->rtp, &us);
- ast_mutex_unlock(&pvt->lock);
-
- strncpy(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
- info->addr[sizeof(info->addr)-1] = '\0';
- info->port = ntohs(us.sin_port);
- if (h323debug)
- ast_log(LOG_DEBUG, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
- return info;
-}
-
-/**
- * Definition taken from rtp.c for rtpPayloadType because we need it here.
- */
-struct rtpPayloadType {
- int isAstFormat; /* whether the following code is an AST_FORMAT */
- int code;
-};
-
-/**
- * Call-back function passing remote ip/port information from H.323 to asterisk
- *
- * Returns nothing
- */
-static void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt)
-{
- struct oh323_pvt *pvt;
- struct sockaddr_in them;
- struct rtpPayloadType rtptype;
-
- if (h323debug)
- ast_log(LOG_DEBUG, "Setting up RTP connection for %s\n", token);
-
- /* Find the call or allocate a private structure if call not found */
- pvt = find_call_locked(call_reference, token);
- if (!pvt) {
- ast_log(LOG_ERROR, "Something is wrong: rtp\n");
- return;
- }
- if (pvt->alreadygone) {
- ast_mutex_unlock(&pvt->lock);
- return;
- }
- rtptype = ast_rtp_lookup_pt(pvt->rtp, pt);
- pvt->nativeformats = rtptype.code;
- if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
- pvt->owner->nativeformats = pvt->nativeformats;
- ast_set_read_format(pvt->owner, pvt->owner->readformat);
- ast_set_write_format(pvt->owner, pvt->owner->writeformat);
- if (pvt->options.progress_audio)
- ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);
- ast_channel_unlock(pvt->owner);
- }
- else {
- if (pvt->options.progress_audio)
- pvt->newcontrol = AST_CONTROL_PROGRESS;
- if (h323debug)
- ast_log(LOG_DEBUG, "RTP connection preparation for %s is pending...\n", token);
- }
-
- them.sin_family = AF_INET;
- /* only works for IPv4 */
- them.sin_addr.s_addr = inet_addr(remoteIp);
- them.sin_port = htons(remotePort);
- ast_rtp_set_peer(pvt->rtp, &them);
-
- ast_mutex_unlock(&pvt->lock);
-
- if (h323debug)
- ast_log(LOG_DEBUG, "RTP connection prepared for %s\n", token);
-
- return;
-}
-
-/**
- * Call-back function to signal asterisk that the channel has been answered
- * Returns nothing
- */
-static void connection_made(unsigned call_reference, const char *token)
-{
- struct oh323_pvt *pvt;
-
- if (h323debug)
- ast_log(LOG_DEBUG, "Call %s answered\n", token);
-
- pvt = find_call_locked(call_reference, token);
- if (!pvt) {
- ast_log(LOG_ERROR, "Something is wrong: connection\n");
- return;
- }
-
- /* Inform asterisk about remote party connected only on outgoing calls */
- if (!pvt->outgoing) {
- ast_mutex_unlock(&pvt->lock);
- return;
- }
- update_state(pvt, AST_STATE_UP, AST_CONTROL_ANSWER);
- ast_mutex_unlock(&pvt->lock);
- return;
-}
-
-static int progress(unsigned call_reference, const char *token, int inband)
-{
- struct oh323_pvt *pvt;
-
- ast_log(LOG_DEBUG, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
-
- pvt = find_call_locked(call_reference, token);
- if (!pvt) {
- ast_log(LOG_ERROR, "Private structure not found in progress.\n");
- return -1;
- }
- if (!pvt->owner) {
- ast_mutex_unlock(&pvt->lock);
- ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");
- return -1;
- }
- update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));
- ast_mutex_unlock(&pvt->lock);
-
- return 0;
-}
-
-/**
- * Call-back function for incoming calls
- *
- * Returns 1 on success
- */
-static call_options_t *setup_incoming_call(call_details_t *cd)
-{
- struct oh323_pvt *pvt;
- struct oh323_user *user = NULL;
- struct oh323_alias *alias = NULL;
-
- if (h323debug)
- ast_log(LOG_DEBUG, "Setting up incoming call for %s\n", cd->call_token);
-
- /* allocate the call*/
- pvt = oh323_alloc(cd->call_reference);
-
- if (!pvt) {
- ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
- cleanup_call_details(cd);
- return NULL;
- }
-
- /* Populate the call details in the private structure */
- memcpy(&pvt->cd, cd, sizeof(pvt->cd));
- memcpy(&pvt->options, &global_options, sizeof(pvt->options));
- pvt->jointcapability = pvt->options.capability;
-
- if (h323debug) {
- ast_verbose(VERBOSE_PREFIX_3 "Setting up Call\n");
- ast_verbose(VERBOSE_PREFIX_3 "\tCall token: [%s]\n", pvt->cd.call_token);
- ast_verbose(VERBOSE_PREFIX_3 "\tCalling party name: [%s]\n", pvt->cd.call_source_name);
- ast_verbose(VERBOSE_PREFIX_3 "\tCalling party number: [%s]\n", pvt->cd.call_source_e164);
- ast_verbose(VERBOSE_PREFIX_3 "\tCalled party name: [%s]\n", pvt->cd.call_dest_alias);
- ast_verbose(VERBOSE_PREFIX_3 "\tCalled party number: [%s]\n", pvt->cd.call_dest_e164);
- ast_verbose(VERBOSE_PREFIX_3 "\tCalling party IP: [%s]\n", pvt->cd.sourceIp);
- }
-
- /* Decide if we are allowing Gatekeeper routed calls*/
- if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && (usingGk)) {
- if (!ast_strlen_zero(cd->call_dest_e164)) {
- strncpy(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten) - 1);
- strncpy(pvt->context, default_context, sizeof(pvt->context) - 1);
- } else {
- alias = find_alias(cd->call_dest_alias);
- if (!alias) {
- ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias);
- oh323_destroy(pvt);
- return NULL;
- }
- strncpy(pvt->exten, alias->name, sizeof(pvt->exten) - 1);
- strncpy(pvt->context, alias->context, sizeof(pvt->context) - 1);
- }
- } else {
- /* Either this call is not from the Gatekeeper
- or we are not allowing gk routed calls */
- user = find_user(cd, 0);
- if (!user) {
- if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
- strncpy(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten) - 1);
- } else {
- strncpy(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten) - 1);
- }
- if (ast_strlen_zero(default_context)) {
- ast_log(LOG_ERROR, "Call from '%s' rejected due to no default context\n", pvt->cd.call_source_aliases);
- oh323_destroy(pvt);
- return NULL;
- }
- strncpy(pvt->context, default_context, sizeof(pvt->context) - 1);
- ast_log(LOG_DEBUG, "Sending %s to context [%s]\n", cd->call_source_aliases, pvt->context);
- /* XXX: Is it really required??? */
-#if 0
- memset(&pvt->options, 0, sizeof(pvt->options));
-#endif
- } else {
- if (user->host) {
- if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) {
- if (ast_strlen_zero(user->context)) {
- if (ast_strlen_zero(default_context)) {
- ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp);
- oh323_destroy(pvt);
- ASTOBJ_UNREF(user, oh323_destroy_user);
- return NULL;
- }
- strncpy(pvt->context, default_context, sizeof(pvt->context) - 1);
- } else {
- strncpy(pvt->context, user->context, sizeof(pvt->context) - 1);
- }
- pvt->exten[0] = 'i';
- pvt->exten[1] = '\0';
- ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp);
- oh323_destroy(pvt);
- ASTOBJ_UNREF(user, oh323_destroy_user);
- return NULL; /* XXX: Hmmm... Why to setup context if we drop connection immediately??? */
- }
- }
- strncpy(pvt->context, user->context, sizeof(pvt->context) - 1);
- memcpy(&pvt->options, &user->options, sizeof(pvt->options));
- pvt->jointcapability = pvt->options.capability;
- if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
- strncpy(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten) - 1);
- } else {
- strncpy(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten) - 1);
- }
- if (!ast_strlen_zero(user->accountcode)) {
- strncpy(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode) - 1);
- }
- if (user->amaflags) {
- pvt->amaflags = user->amaflags;
- }
- ASTOBJ_UNREF(user, oh323_destroy_user);
- }
- }
- return &pvt->options;
-}
-
-/**
- * Call-back function to start PBX when OpenH323 ready to serve incoming call
- *
- * Returns 1 on success
- */
-static int answer_call(unsigned call_reference, const char *token)
-{
- struct oh323_pvt *pvt;
- struct ast_channel *c = NULL;
-
- if (h323debug)
- ast_log(LOG_DEBUG, "Preparing Asterisk to answer for %s\n", token);
-
- /* Find the call or allocate a private structure if call not found */
- pvt = find_call_locked(call_reference, token);
- if (!pvt) {
- ast_log(LOG_ERROR, "Something is wrong: answer_call\n");
- return 0;
- }
- /* allocate a channel and tell asterisk about it */
- c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token);
-
- /* And release when done */
- ast_mutex_unlock(&pvt->lock);
- if (!c) {
- ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n");
- return 0;
- }
- return 1;
-}
-
-/**
- * Call-back function to establish an outgoing H.323 call
- *
- * Returns 1 on success
- */
-static int setup_outgoing_call(call_details_t *cd)
-{
- /* Use argument here or free it immediately */
- cleanup_call_details(cd);
-
- return 1;
-}
-
-/**
- * Call-back function to signal asterisk that the channel is ringing
- * Returns nothing
- */
-static void chan_ringing(unsigned call_reference, const char *token)
-{
- struct oh323_pvt *pvt;
-
- if (h323debug)
- ast_log(LOG_DEBUG, "Ringing on %s\n", token);
-
- pvt = find_call_locked(call_reference, token);
- if (!pvt) {
- ast_log(LOG_ERROR, "Something is wrong: ringing\n");
- return;
- }
- if (!pvt->owner) {
- ast_mutex_unlock(&pvt->lock);
- ast_log(LOG_ERROR, "Channel has no owner\n");
- return;
- }
- update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING);
- ast_mutex_unlock(&pvt->lock);
- return;
-}
-
-/**
- * Call-back function to cleanup communication
- * Returns nothing,
- */
-static void cleanup_connection(unsigned call_reference, const char *call_token)
-{
- struct oh323_pvt *pvt;
-
- ast_log(LOG_DEBUG, "Cleaning connection to %s\n", call_token);
-
- while (1) {
- pvt = find_call_locked(call_reference, call_token);
- if (!pvt) {
- if (h323debug)
- ast_log(LOG_DEBUG, "No connection for %s\n", call_token);
- return;
- }
- if (!pvt->owner || !ast_channel_trylock(pvt->owner))
- break;
-#if 1
-#ifdef DEBUG_THREADS
- 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[0], pvt->owner->lock.reentrancy, pvt->owner->lock.func[0], pvt->owner->lock.file[0], pvt->owner->lock.lineno[0]);
-#else
- ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token);
-#endif
-#endif
- ast_mutex_unlock(&pvt->lock);
- usleep(1);
- }
- if (pvt->rtp) {
- /* Immediately stop RTP */
- ast_rtp_destroy(pvt->rtp);
- pvt->rtp = NULL;
- }
- /* Free dsp used for in-band DTMF detection */
- if (pvt->vad) {
- ast_dsp_free(pvt->vad);
- pvt->vad = NULL;
- }
- cleanup_call_details(&pvt->cd);
- pvt->alreadygone = 1;
- /* Send hangup */
- if (pvt->owner) {
- pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
- ast_queue_hangup(pvt->owner);
- ast_channel_unlock(pvt->owner);
- }
- ast_mutex_unlock(&pvt->lock);
- if (h323debug)
- ast_log(LOG_DEBUG, "Connection to %s cleaned\n", call_token);
- return;
-}
-
-static void hangup_connection(unsigned int call_reference, const char *token, int cause)
-{
- struct oh323_pvt *pvt;
-
- if (h323debug) {
- ast_log(LOG_DEBUG, "Hanging up connection to %s with cause %d\n", token, cause);
- }
-
- pvt = find_call_locked(call_reference, token);
- if (!pvt) {
- if (h323debug) {
- ast_log(LOG_DEBUG, "Connection to %s already cleared\n", token);
- }
- return;
- }
- if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
- pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
- pvt->owner->hangupcause = pvt->hangupcause = cause;
- ast_queue_hangup(pvt->owner);
- ast_channel_unlock(pvt->owner);
- }
- else {
- pvt->needhangup = 1;
- pvt->hangupcause = cause;
- ast_log(LOG_DEBUG, "Hangup for %s is pending\n", token);
- }
- ast_mutex_unlock(&pvt->lock);
-}
-
-static void set_dtmf_payload(unsigned call_reference, const char *token, int payload)
-{
- struct oh323_pvt *pvt;
-
- if (h323debug)
- ast_log(LOG_DEBUG, "Setting DTMF payload to %d on %s\n", payload, token);
-
- pvt = find_call_locked(call_reference, token);
- if (!pvt) {
- return;
- }
- if (pvt->rtp) {
- ast_rtp_set_rtpmap_type(pvt->rtp, payload, "audio", "telephone-event", 0);
- }
- pvt->dtmf_pt = payload;
- ast_mutex_unlock(&pvt->lock);
- if (h323debug)
- ast_log(LOG_DEBUG, "DTMF payload on %s set to %d\n", token, payload);
-}
-
-static void set_peer_capabilities(unsigned call_reference, const char *token, int capabilities)
-{
- struct oh323_pvt *pvt;
-
- if (h323debug)
- ast_log(LOG_DEBUG, "Got remote capabilities from connection %s\n", token);
-
- pvt = find_call_locked(call_reference, token);
- if (!pvt)
- return;
- pvt->peercapability = capabilities;
- pvt->jointcapability = pvt->options.capability & capabilities;
- ast_mutex_unlock(&pvt->lock);
-}
-
-static void set_local_capabilities(unsigned call_reference, const char *token)
-{
- struct oh323_pvt *pvt;
- int capability, dtmfmode, pref_codec;
- struct ast_codec_pref prefs;
-
- if (h323debug)
- ast_log(LOG_DEBUG, "Setting capabilities for connection %s\n", token);
-
- pvt = find_call_locked(call_reference, token);
- if (!pvt)
- return;
- capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
- dtmfmode = pvt->options.dtmfmode;
- prefs = pvt->options.prefs;
- pref_codec = pvt->pref_codec;
- ast_mutex_unlock(&pvt->lock);
- h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
-
- if (h323debug)
- ast_log(LOG_DEBUG, "Capabilities for connection %s is set\n", token);
-}
-
-static void *do_monitor(void *data)
-{
- int res;
- int reloading;
- struct oh323_pvt *oh323 = NULL;
-
- for(;;) {
- /* Check for a reload request */
- ast_mutex_lock(&h323_reload_lock);
- reloading = h323_reloading;
- h323_reloading = 0;
- ast_mutex_unlock(&h323_reload_lock);
- if (reloading) {
- if (option_verbose > 0) {
- ast_verbose(VERBOSE_PREFIX_1 "Reloading H.323\n");
- }
- h323_do_reload();
- }
- /* Check for interfaces needing to be killed */
- ast_mutex_lock(&iflock);
-#if 1
- do {
- for (oh323 = iflist; oh323; oh323 = oh323->next) {
- if (oh323->needdestroy) {
- __oh323_destroy(oh323);
- break;
- }
- }
- } while (oh323);
-#else
-restartsearch:
- oh323 = iflist;
- while(oh323) {
- if (oh323->needdestroy) {
- __oh323_destroy(oh323);
- goto restartsearch;
- }
- oh323 = oh323->next;
- }
-#endif
- ast_mutex_unlock(&iflock);
- pthread_testcancel();
- /* Wait for sched or io */
- res = ast_sched_wait(sched);
- if ((res < 0) || (res > 1000)) {
- res = 1000;
- }
- res = ast_io_wait(io, res);
- pthread_testcancel();
- ast_mutex_lock(&monlock);
- if (res >= 0) {
- ast_sched_runq(sched);
- }
- ast_mutex_unlock(&monlock);
- }
- /* Never reached */
- return NULL;
-}
-
-static int restart_monitor(void)
-{
- pthread_attr_t attr;
- /* If we're supposed to be stopped -- stay stopped */
- if (ast_mutex_lock(&monlock)) {
- ast_log(LOG_WARNING, "Unable to lock monitor\n");
- return -1;
- }
- if (monitor_thread == AST_PTHREADT_STOP) {
- ast_mutex_unlock(&monlock);
- return 0;
- }
- if (monitor_thread == pthread_self()) {
- ast_mutex_unlock(&monlock);
- ast_log(LOG_WARNING, "Cannot kill myself\n");
- return -1;
- }
- if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) {
- /* Wake up the thread */
- pthread_kill(monitor_thread, SIGURG);
- } else {
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- /* Start a new monitor */
- if (ast_pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
- monitor_thread = AST_PTHREADT_NULL;
- ast_mutex_unlock(&monlock);
- ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
- return -1;
- }
- }
- ast_mutex_unlock(&monlock);
- return 0;
-}
-
-static int h323_do_trace(int fd, int argc, char *argv[])
-{
- if (argc != 3) {
- return RESULT_SHOWUSAGE;
- }
- h323_debug(1, atoi(argv[2]));
- ast_cli(fd, "H.323 trace set to level %s\n", argv[2]);
- return RESULT_SUCCESS;
-}
-
-static int h323_no_trace(int fd, int argc, char *argv[])
-{
- if (argc != 3) {
- return RESULT_SHOWUSAGE;
- }
- h323_debug(0,0);
- ast_cli(fd, "H.323 trace disabled\n");
- return RESULT_SUCCESS;
-}
-
-static int h323_do_debug(int fd, int argc, char *argv[])
-{
- if (argc != 2) {
- return RESULT_SHOWUSAGE;
- }
- h323debug = 1;
- ast_cli(fd, "H323 debug enabled\n");
- return RESULT_SUCCESS;
-}
-
-static int h323_no_debug(int fd, int argc, char *argv[])
-{
- if (argc != 3) {
- return RESULT_SHOWUSAGE;
- }
- h323debug = 0;
- ast_cli(fd, "H323 Debug disabled\n");
- return RESULT_SUCCESS;
-}
-
-static int h323_gk_cycle(int fd, int argc, char *argv[])
-{
-#if 0
- if (argc != 3) {
- return RESULT_SHOWUSAGE;
- }
- h323_gk_urq();
-
- /* Possibly register with a GK */
- if (!gatekeeper_disable) {
- if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
- ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
- }
- }
-#endif
- return RESULT_SUCCESS;
-}
-
-static int h323_ep_hangup(int fd, int argc, char *argv[])
-{
- if (argc != 3) {
- return RESULT_SHOWUSAGE;
- }
- if (h323_soft_hangup(argv[2])) {
- ast_verbose(VERBOSE_PREFIX_3 "Hangup succeeded on %s\n", argv[2]);
- } else {
- ast_verbose(VERBOSE_PREFIX_3 "Hangup failed for %s\n", argv[2]);
- }
- return RESULT_SUCCESS;
-}
-
-static int h323_tokens_show(int fd, int argc, char *argv[])
-{
- if (argc != 3) {
- return RESULT_SHOWUSAGE;
- }
- h323_show_tokens();
- return RESULT_SUCCESS;
-}
-
-static char trace_usage[] =
-"Usage: h.323 trace <level num>\n"
-" Enables H.323 stack tracing for debugging purposes\n";
-
-static char no_trace_usage[] =
-"Usage: h.323 no trace\n"
-" Disables H.323 stack tracing for debugging purposes\n";
-
-static char debug_usage[] =
-"Usage: h.323 debug\n"
-" Enables H.323 debug output\n";
-
-static char no_debug_usage[] =
-"Usage: h.323 no debug\n"
-" Disables H.323 debug output\n";
-
-static char show_codec_usage[] =
-"Usage: h.323 show codec\n"
-" Shows all enabled codecs\n";
-
-static char show_cycle_usage[] =
-"Usage: h.323 gk cycle\n"
-" Manually re-register with the Gatekeper (Currently Disabled)\n";
-
-static char show_hangup_usage[] =
-"Usage: h.323 hangup <token>\n"
-" Manually try to hang up call identified by <token>\n";
-
-static char show_tokens_usage[] =
-"Usage: h.323 show tokens\n"
-" Print out all active call tokens\n";
-
-static char h323_reload_usage[] =
-"Usage: h323 reload\n"
-" Reloads H.323 configuration from sip.conf\n";
-
-static struct ast_cli_entry h323_cli[] = {
- { { "h.323", "trace", NULL }, h323_do_trace,
- "Enable H.323 Stack Tracing", trace_usage },
- { { "h.323", "no", "trace", NULL }, h323_no_trace,
- "Disable H.323 Stack Tracing", no_trace_usage },
- { { "h.323", "debug", NULL }, h323_do_debug,
- "Enable H.323 debug", debug_usage },
- { { "h.323", "no", "debug", NULL }, h323_no_debug,
- "Disable H.323 debug", no_debug_usage },
- { { "h.323", "show", "codecs", NULL }, h323_show_codec,
- "Show enabled codecs", show_codec_usage },
- { { "h.323", "gk", "cycle", NULL }, h323_gk_cycle,
- "Manually re-register with the Gatekeper", show_cycle_usage },
- { { "h.323", "hangup", NULL }, h323_ep_hangup,
- "Manually try to hang up a call", show_hangup_usage },
- { { "h.323", "show", "tokens", NULL }, h323_tokens_show,
- "Show all active call tokens", show_tokens_usage },
-};
+ if (strcasecmp(v->value, "h323")) {
+ ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->value);
+ }
+ }
+ }
+ ASTOBJ_UNMARK(alias);
+ return alias;
+}
static int update_common_options(struct ast_variable *v, struct call_options *options)
{
@@ -2000,41 +1061,6 @@
return 0;
}
-static struct oh323_alias *build_alias(char *name, struct ast_variable *v)
-{
- struct oh323_alias *alias;
- int found = 0;
-
- alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&aliasl, name, name, 0, 0, strcasecmp);
-
- if (alias)
- found++;
- else {
- if (!(alias = (struct oh323_alias *)calloc(1, sizeof(*alias))))
- return NULL;
- ASTOBJ_INIT(alias);
- }
- if (!found && name)
- strncpy(alias->name, name, sizeof(alias->name) - 1);
- for (; v; v = v->next) {
- if (!strcasecmp(v->name, "e164")) {
- strncpy(alias->e164, v->value, sizeof(alias->e164) - 1);
- } else if (!strcasecmp(v->name, "prefix")) {
- strncpy(alias->prefix, v->value, sizeof(alias->prefix) - 1);
- } else if (!strcasecmp(v->name, "context")) {
- strncpy(alias->context, v->value, sizeof(alias->context) - 1);
- } else if (!strcasecmp(v->name, "secret")) {
- strncpy(alias->secret, v->value, sizeof(alias->secret) - 1);
- } else {
- if (strcasecmp(v->value, "h323")) {
- ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->value);
- }
- }
- }
- ASTOBJ_UNMARK(alias);
- return alias;
-}
-
static struct oh323_user *build_user(char *name, struct ast_variable *v, int realtime)
{
struct oh323_user *user;
@@ -2058,6 +1084,14 @@
strncpy(user->context, default_context, sizeof(user->context) - 1);
if (user && !found)
strncpy(user->name, name, sizeof(user->name) - 1);
+
+#if 0 /* XXX Port channel variables functionality from chan_sip XXX */
+ if (user->chanvars) {
+ ast_variables_destroy(user->chanvars);
+ user->chanvars = NULL;
+ }
+#endif
+
for (; v; v = v->next) {
if (!update_common_options(v, &user->options))
continue;
@@ -2097,7 +1131,45 @@
return user;
}
-static struct oh323_peer *build_peer(char *name, struct ast_variable *v, int realtime)
+static struct oh323_user *realtime_user(const call_details_t *cd)
+{
+ struct ast_variable *var, *tmp;
+ struct oh323_user *user;
+ char *username;
+
+ if (userbyalias)
+ var = ast_load_realtime("h323", "name", username = cd->call_source_aliases, NULL);
+ else {
+ username = (char *)NULL;
+ var = ast_load_realtime("h323", "host", cd->sourceIp, NULL);
+ }
+
+ if (!var)
+ return NULL;
+
+ for (tmp = var; tmp; tmp = tmp->next) {
+ if (!strcasecmp(tmp->name, "type") &&
+ !(!strcasecmp(tmp->value, "user") || !strcasecmp(tmp->value, "friend"))) {
+ ast_variables_destroy(var);
+ return NULL;
+ } else if (!username && !strcasecmp(tmp->name, "name"))
+ username = tmp->value;
+ }
+
+ if (!username) {
+ ast_log(LOG_WARNING, "Cannot determine user name for IP address %s\n", cd->sourceIp);
+ ast_variables_destroy(var);
+ return NULL;
+ }
+
+ user = build_user(username, var, 1);
+
+ ast_variables_destroy(var);
+
+ return user;
+}
+
+static struct oh323_peer *build_peer(const char *name, struct ast_variable *v, int realtime)
{
struct oh323_peer *peer;
struct ast_ha *oldha;
@@ -2119,6 +1191,7 @@
peer->addr.sin_family = AF_INET;
if (!found && name)
strncpy(peer->name, name, sizeof(peer->name) - 1);
+
#if 0 /* XXX Port channel variables functionality from chan_sip XXX */
if (peer->chanvars) {
ast_variables_destroy(peer->chanvars);
@@ -2151,6 +1224,1019 @@
ast_free_ha(oldha);
return peer;
}
+
+static struct oh323_peer *realtime_peer(const char *peername, struct sockaddr_in *sin)
+{
+ struct oh323_peer *peer;
+ struct ast_variable *var;
+ struct ast_variable *tmp;
+ const char *addr;
+
+ /* First check on peer name */
+ if (peername)
+ var = ast_load_realtime("h323", "name", peername, NULL);
+ else if (sin) /* Then check on IP address for dynamic peers */
+ var = ast_load_realtime("h323", "host", addr = ast_inet_ntoa(sin->sin_addr), NULL);
+ else
+ return NULL;
+
+ if (!var)
+ return NULL;
+
+ for (tmp = var; tmp; tmp = tmp->next) {
+ /* If this is type=user, then skip this object. */
+ if (!strcasecmp(tmp->name, "type") &&
+ !(!strcasecmp(tmp->value, "peer") || !strcasecmp(tmp->value, "friend"))) {
+ ast_variables_destroy(var);
+ return NULL;
+ } else if (!peername && !strcasecmp(tmp->name, "name")) {
+ peername = tmp->value;
+ }
+ }
+
+ if (!peername) { /* Did not find peer in realtime */
+ ast_log(LOG_WARNING, "Cannot determine peer name for IP address %s\n", addr);
+ ast_variables_destroy(var);
+ return NULL;
+ }
+
+ /* Peer found in realtime, now build it in memory */
+ peer = build_peer(peername, var, 1);
+
+ ast_variables_destroy(var);
+
+ return peer;
+}
+
+static int oh323_addrcmp_str(struct in_addr inaddr, char *addr)
+{
+ return strcmp(ast_inet_ntoa(inaddr), addr);
+}
+
+static struct oh323_user *find_user(const call_details_t *cd, int realtime)
+{
+ struct oh323_user *u;
+
+ if (userbyalias)
+ u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases);
+ else
+ u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str);
+
+ if (!u && realtime)
+ u = realtime_user(cd);
+
+ if (!u && h323debug)
+ ast_log(LOG_DEBUG, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp);
+
+ return u;
+}
+
+static int oh323_addrcmp(struct sockaddr_in addr, struct sockaddr_in *sin)
+{
+ int res;
+
+ if (!sin)
+ res = -1;
+ else
+ res = inaddrcmp(&addr , sin);
+
+ return res;
+}
+
+static struct oh323_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime)
+{
+ struct oh323_peer *p;
+
+ if (peer)
+ p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
+ else
+ p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
+
+ if (!p && realtime)
+ p = realtime_peer(peer, sin);
+
+ if (!p && h323debug)
+ ast_log(LOG_DEBUG, "Could not find peer by name %s or address %s\n", (peer ? peer : "<NONE>"), (sin ? ast_inet_ntoa(sin->sin_addr) : "<NONE>"));
+
+ return p;
+}
+
+static int create_addr(struct oh323_pvt *pvt, char *opeer)
+{
+ struct hostent *hp;
+ struct ast_hostent ahp;
+ struct oh323_peer *p;
+ int portno;
+ int found = 0;
+ char *port;
+ char *hostn;
+ char peer[256] = "";
+
+ strncpy(peer, opeer, sizeof(peer) - 1);
+ port = strchr(peer, ':');
+ if (port) {
+ *port = '\0';
+ port++;
+ }
+ pvt->sa.sin_family = AF_INET;
+ p = find_peer(peer, NULL, 0);
+ if (p) {
+ found++;
+ memcpy(&pvt->options, &p->options, sizeof(pvt->options));
+ pvt->jointcapability = pvt->options.capability;
+ if (pvt->rtp) {
+ ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat);
+ ast_rtp_setnat(pvt->rtp, pvt->options.nat);
+ }
+ if (pvt->options.dtmfmode) {
+ if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
+ pvt->nonCodecCapability |= AST_RTP_DTMF;
+ } else {
+ pvt->nonCodecCapability &= ~AST_RTP_DTMF;
+ }
+ }
+ if (p->addr.sin_addr.s_addr) {
+ pvt->sa.sin_addr = p->addr.sin_addr;
+ pvt->sa.sin_port = p->addr.sin_port;
+ }
+ ASTOBJ_UNREF(p, oh323_destroy_peer);
+ }
+ if (!p && !found) {
+ hostn = peer;
+ if (port) {
+ portno = atoi(port);
+ } else {
+ portno = h323_signalling_port;
+ }
+ hp = ast_gethostbyname(hostn, &ahp);
+ if (hp) {
+ memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
+ pvt->sa.sin_port = htons(portno);
+ /* Look peer by address */
+ p = find_peer(NULL, &pvt->sa, 0);
+ memcpy(&pvt->options, (p ? &p->options : &global_options), sizeof(pvt->options));
+ pvt->jointcapability = pvt->options.capability;
+ if (p) {
+ ASTOBJ_UNREF(p, oh323_destroy_peer);
+ }
+ if (pvt->rtp) {
+ ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat);
+ ast_rtp_setnat(pvt->rtp, pvt->options.nat);
+ }
+ if (pvt->options.dtmfmode) {
+ if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
+ pvt->nonCodecCapability |= AST_RTP_DTMF;
+ } else {
+ pvt->nonCodecCapability &= ~AST_RTP_DTMF;
+ }
+ }
+ return 0;
+ } else {
+ ast_log(LOG_WARNING, "No such host: %s\n", peer);
+ return -1;
+ }
+ } else if (!p) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause)
+{
+ int oldformat;
+ struct oh323_pvt *pvt;
+ struct ast_channel *tmpc = NULL;
+ char *dest = (char *)data;
+ char *ext, *host;
+ char *h323id = NULL;
+ char tmp[256], tmp1[256];
+
+ ast_log(LOG_DEBUG, "type=%s, format=%d, data=%s.\n", type, format, (char *)data);
+ pvt = oh323_alloc(0);
+ if (!pvt) {
+ ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data);
+ return NULL;
+ }
+ oldformat = format;
+ format &= ((AST_FORMAT_MAX_AUDIO << 1) - 1);
+ if (!format) {
+ ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
+ oh323_destroy(pvt);
+ return NULL;
+ }
+ strncpy(tmp, dest, sizeof(tmp) - 1);
+ host = strchr(tmp, '@');
+ if (host) {
+ *host = '\0';
+ host++;
+ ext = tmp;
+ } else {
+ host = tmp;
+ ext = NULL;
+ }
+ strtok_r(host, "/", &(h323id));
+ if (!ast_strlen_zero(h323id)) {
+ h323_set_id(h323id);
+ }
+ if (ext) {
+ strncpy(pvt->exten, ext, sizeof(pvt->exten) - 1);
+ }
+ ast_log(LOG_DEBUG, "Extension: %s Host: %s\n", pvt->exten, host);
+ if (!usingGk) {
+ if (create_addr(pvt, host)) {
+ oh323_destroy(pvt);
+ return NULL;
+ }
+ }
+ else {
+ memcpy(&pvt->options, &global_options, sizeof(pvt->options));
+ pvt->jointcapability = pvt->options.capability;
+ if (pvt->rtp) {
+ ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat);
+ ast_rtp_setnat(pvt->rtp, pvt->options.nat);
+ }
+ if (pvt->options.dtmfmode) {
+ if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
+ pvt->nonCodecCapability |= AST_RTP_DTMF;
+ } else {
+ pvt->nonCodecCapability &= ~AST_RTP_DTMF;
+ }
+ }
+ }
+
+ ast_mutex_lock(&caplock);
+ /* Generate unique channel identifier */
+ snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
+ tmp1[sizeof(tmp1)-1] = '\0';
+ ast_mutex_unlock(&caplock);
+
+ ast_mutex_lock(&pvt->lock);
+ tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1);
+ ast_mutex_unlock(&pvt->lock);
+ if (!tmpc) {
+ oh323_destroy(pvt);
+ }
+ ast_update_use_count();
+ restart_monitor();
+ return tmpc;
+}
+
+/** Find a call by alias */
+static struct oh323_alias *find_alias(const char *source_aliases)
+{
+ struct oh323_alias *a;
+
+ a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
+
+#if 0 /* XXX REALTIME XXX */
+ if (!a && realtime)
+ a = realtime_alias(source_aliases);
+#endif
+
+ return a;
+}
+
+/**
+ * Callback for sending digits from H.323 up to asterisk
+ *
+ */
+static int send_digit(unsigned call_reference, char digit, const char *token)
+{
+ struct oh323_pvt *pvt;
+ int res;
+
+ if (digit == ' ') /* DTMF tone update -- ignore */
+ return 0;
+ ast_log(LOG_DEBUG, "Received Digit: %c\n", digit);
[... 733 lines stripped ...]
More information about the asterisk-commits
mailing list