#include "asterisk.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "asterisk/lock.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/musiconhold.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/dsp.h"
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/astobj.h"
#include "h323/chan_h323.h"
Include dependency graph for chan_h323.c:

Go to the source code of this file.
Data Structures | |
| struct | ast_alias_list |
| struct | ast_peer_list |
| The peer list: Peers and Friends. More... | |
| struct | ast_user_list |
| The user list: Users and friends. More... | |
| struct | oh323_pvt |
| struct | rtpPayloadType |
| Structure representing a RTP session.The value of each payload format mapping:. More... | |
Defines | |
| #define | DEPRECATED(_v, _new_opt) ast_log(LOG_WARNING, "Option %s found at line %d has beed deprecated. Use %s instead.\n", (_v)->name, (_v)->lineno, (_new_opt)) |
| #define | GLOBAL_CAPABILITY (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_H261) |
Functions | |
| static void | __oh323_destroy (struct oh323_pvt *pvt) |
| static struct ast_channel * | __oh323_new (struct oh323_pvt *pvt, int state, const char *host) |
| static int | __oh323_rtp_create (struct oh323_pvt *pvt) |
| static void | __oh323_update_info (struct ast_channel *c, struct oh323_pvt *pvt) |
| static int | answer_call (unsigned call_reference, const char *token) |
| AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"The NuFone Network's OpenH323 Channel Driver",.load=load_module,.unload=unload_module,.reload=reload,) | |
| AST_MUTEX_DEFINE_STATIC (h323_reload_lock) | |
| AST_MUTEX_DEFINE_STATIC (caplock) | |
| AST_MUTEX_DEFINE_STATIC (monlock) | |
| AST_MUTEX_DEFINE_STATIC (iflock) | |
| static struct oh323_alias * | build_alias (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime) |
| static struct oh323_peer * | build_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime) |
| static struct oh323_user * | build_user (char *name, struct ast_variable *v, struct ast_variable *alt, int realtime) |
| static void | chan_ringing (unsigned call_reference, const char *token) |
| static void | cleanup_call_details (call_details_t *cd) |
| static void | cleanup_connection (unsigned call_reference, const char *call_token) |
| static void | connection_made (unsigned call_reference, const char *token) |
| static char * | convertcap (int cap) |
| static int | create_addr (struct oh323_pvt *pvt, char *opeer) |
| static void | delete_aliases (void) |
| static void | delete_users (void) |
| static void * | do_monitor (void *data) |
| static struct rtp_info * | external_rtp_create (unsigned call_reference, const char *token) |
| static struct oh323_alias * | find_alias (const char *source_aliases, int realtime) |
| static struct oh323_pvt * | find_call_locked (int call_reference, const char *token) |
| static struct oh323_peer * | find_peer (const char *peer, struct sockaddr_in *sin, int realtime) |
| static struct oh323_user * | find_user (const call_details_t *cd, int realtime) |
| static int | h323_do_debug (int fd, int argc, char *argv[]) |
| static int | h323_do_reload (void) |
| static int | h323_do_trace (int fd, int argc, char *argv[]) |
| static int | h323_ep_hangup (int fd, int argc, char *argv[]) |
| static int | h323_gk_cycle (int fd, int argc, char *argv[]) |
| static int | h323_no_debug (int fd, int argc, char *argv[]) |
| static int | h323_no_trace (int fd, int argc, char *argv[]) |
| static int | h323_reload (int fd, int argc, char *argv[]) |
| static int | h323_tokens_show (int fd, int argc, char *argv[]) |
| static void | hangup_connection (unsigned int call_reference, const char *token, int cause) |
| static enum ast_module_load_result | load_module (void) |
| static int | oh323_addrcmp (struct sockaddr_in addr, struct sockaddr_in *sin) |
| static int | oh323_addrcmp_str (struct in_addr inaddr, char *addr) |
| static struct oh323_pvt * | oh323_alloc (int callid) |
| static int | oh323_answer (struct ast_channel *c) |
| static int | oh323_call (struct ast_channel *c, char *dest, int timeout) |
| static void | oh323_destroy (struct oh323_pvt *pvt) |
| static void | oh323_destroy_alias (struct oh323_alias *alias) |
| static void | oh323_destroy_peer (struct oh323_peer *peer) |
| static void | oh323_destroy_user (struct oh323_user *user) |
| static int | oh323_digit_begin (struct ast_channel *c, char digit) |
| static int | oh323_digit_end (struct ast_channel *c, char digit, unsigned int duration) |
| static int | oh323_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
| static enum ast_rtp_get_result | oh323_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp) |
| static enum ast_rtp_get_result | oh323_get_vrtp_peer (struct ast_channel *chan, struct ast_rtp **rtp) |
| static int | oh323_hangup (struct ast_channel *c) |
| static int | oh323_indicate (struct ast_channel *c, int condition, const void *data, size_t datalen) |
| static struct ast_frame * | oh323_read (struct ast_channel *c) |
| static struct ast_channel * | oh323_request (const char *type, int format, void *data, int *cause) |
| static struct ast_frame * | oh323_rtp_read (struct oh323_pvt *pvt) |
| static int | oh323_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active) |
| static int | oh323_simulate_dtmf_end (const void *data) |
| static void | oh323_update_info (struct ast_channel *c) |
| static int | oh323_write (struct ast_channel *c, struct ast_frame *frame) |
| static int | progress (unsigned call_reference, const char *token, int inband) |
| static void | prune_peers (void) |
| static struct oh323_alias * | realtime_alias (const char *alias) |
| static struct oh323_peer * | realtime_peer (const char *peername, struct sockaddr_in *sin) |
| static struct oh323_user * | realtime_user (const call_details_t *cd) |
| static int | receive_digit (unsigned call_reference, char digit, const char *token, int duration) |
| static const char * | redirectingreason2str (int redirectingreason) |
| static int | reload (void) |
| static int | reload_config (int is_reload) |
| static int | restart_monitor (void) |
| static void | set_dtmf_payload (unsigned call_reference, const char *token, int payload) |
| static void | set_local_capabilities (unsigned call_reference, const char *token) |
| static void | set_peer_capabilities (unsigned call_reference, const char *token, int capabilities, struct ast_codec_pref *prefs) |
| static call_options_t * | setup_incoming_call (call_details_t *cd) |
| static int | setup_outgoing_call (call_details_t *cd) |
| static void | setup_rtp_connection (unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt) |
| static int | unload_module (void) |
| static int | update_common_options (struct ast_variable *v, struct call_options *options) |
| static int | update_state (struct oh323_pvt *pvt, int state, int signal) |
Variables | |
| static int | acceptAnonymous = 1 |
| static struct ast_alias_list | aliasl |
| static struct sockaddr_in | bindaddr |
| static struct ast_cli_entry | cli_h323 [] |
| static struct ast_cli_entry | cli_h323_debug_deprecated |
| static struct ast_cli_entry | cli_h323_gk_cycle_deprecated |
| static struct ast_cli_entry | cli_h323_no_debug_deprecated |
| static struct ast_cli_entry | cli_h323_no_trace_deprecated |
| static struct ast_cli_entry | cli_h323_reload |
| static struct ast_cli_entry | cli_h323_trace_deprecated |
| static const char | config [] = "h323.conf" |
| static char | debug_usage [] |
| static char | default_context [AST_MAX_CONTEXT] = "default" |
| static struct ast_jb_conf | default_jbconf |
| static char | gatekeeper [100] |
| static int | gatekeeper_disable = 1 |
| static int | gatekeeper_discover = 0 |
| static int | gkroute = 0 |
| static struct ast_jb_conf | global_jbconf |
| static call_options_t | global_options |
| static char | h323_reload_usage [] |
| static int | h323_reloading = 0 |
| static int | h323_signalling_port = 1720 |
| int | h323debug |
| oh323_pvt * | iflist |
| static struct io_context * | io |
| static pthread_t | monitor_thread = AST_PTHREADT_NULL |
| static char | no_debug_usage [] |
| static char | no_trace_usage [] |
| static struct ast_rtp_protocol | oh323_rtp |
| static struct ast_channel_tech | oh323_tech |
| answer_call_cb | on_answer_call |
| chan_ringing_cb | on_chan_ringing |
| clear_con_cb | on_connection_cleared |
| con_established_cb | on_connection_established |
| on_rtp_cb | on_external_rtp_create |
| hangup_cb | on_hangup |
| setup_incoming_cb | on_incoming_call |
| setup_outbound_cb | on_outgoing_call |
| progress_cb | on_progress |
| receive_digit_cb | on_receive_digit |
| rfc2833_cb | on_set_rfc2833_payload |
| setcapabilities_cb | on_setcapabilities |
| setpeercapabilities_cb | on_setpeercapabilities |
| start_rtp_cb | on_start_rtp_channel |
| static struct ast_peer_list | peerl |
| static struct sched_context * | sched |
| static char | secret [50] |
| static char | show_cycle_usage [] |
| static char | show_hangup_usage [] |
| static char | show_tokens_usage [] |
| static const char | tdesc [] = "The NuFone Network's Open H.323 Channel Driver" |
| static int | tos = 0 |
| static char | trace_usage [] |
| static unsigned int | unique = 0 |
| static int | userbyalias = 1 |
| static struct ast_user_list | userl |
Definition in file chan_h323.c.
| #define GLOBAL_CAPABILITY (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_H261) |
| static void __oh323_destroy | ( | struct oh323_pvt * | pvt | ) | [static] |
Definition at line 450 of file chan_h323.c.
References ast_channel_lock, ast_channel_unlock, ast_dsp_free(), ast_log(), ast_mutex_destroy(), ast_mutex_unlock(), ast_rtp_destroy(), AST_SCHED_DEL, oh323_pvt::cd, cleanup_call_details(), oh323_pvt::DTMFsched, free, iflist, oh323_pvt::lock, LOG_DEBUG, LOG_WARNING, oh323_pvt::next, oh323_pvt::owner, oh323_pvt::rtp, sched, ast_channel::tech_pvt, and oh323_pvt::vad.
Referenced by do_monitor(), and oh323_destroy().
00451 { 00452 struct oh323_pvt *cur, *prev = NULL; 00453 00454 AST_SCHED_DEL(sched, pvt->DTMFsched); 00455 00456 if (pvt->rtp) { 00457 ast_rtp_destroy(pvt->rtp); 00458 } 00459 00460 /* Free dsp used for in-band DTMF detection */ 00461 if (pvt->vad) { 00462 ast_dsp_free(pvt->vad); 00463 } 00464 cleanup_call_details(&pvt->cd); 00465 00466 /* Unlink us from the owner if we have one */ 00467 if (pvt->owner) { 00468 ast_channel_lock(pvt->owner); 00469 if (h323debug) 00470 ast_log(LOG_DEBUG, "Detaching from %s\n", pvt->owner->name); 00471 pvt->owner->tech_pvt = NULL; 00472 ast_channel_unlock(pvt->owner); 00473 } 00474 cur = iflist; 00475 while(cur) { 00476 if (cur == pvt) { 00477 if (prev) 00478 prev->next = cur->next; 00479 else 00480 iflist = cur->next; 00481 break; 00482 } 00483 prev = cur; 00484 cur = cur->next; 00485 } 00486 if (!cur) { 00487 ast_log(LOG_WARNING, "%p is not in list?!?! \n", cur); 00488 } else { 00489 ast_mutex_unlock(&pvt->lock); 00490 ast_mutex_destroy(&pvt->lock); 00491 free(pvt); 00492 } 00493 }
| static struct ast_channel* __oh323_new | ( | struct oh323_pvt * | pvt, | |
| int | state, | |||
| const char * | host | |||
| ) | [static] |
Definition at line 999 of file chan_h323.c.
References accountcode, oh323_pvt::accountcode, ast_channel::amaflags, oh323_pvt::amaflags, ast_best_codec(), ast_channel_alloc(), ast_codec_choose(), ast_dsp_new(), ast_dsp_set_features(), ast_hangup(), ast_log(), ast_module_ref(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_rtcp_fd(), ast_rtp_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_udptl_fd(), oh323_pvt::cd, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, cid_name, cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_ton, ast_channel::context, oh323_pvt::context, DSP_FEATURE_DTMF_DETECT, ast_channel::exten, oh323_pvt::exten, ast_channel::fds, fmt, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_WARNING, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_tech, oh323_pvt::options, oh323_pvt::owner, pbx_builtin_setvar_helper(), ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, redirectingreason2str(), ast_channel::rings, oh323_pvt::rtp, strdup, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, oh323_pvt::vad, and ast_channel::writeformat.
Referenced by answer_call(), and oh323_request().
01000 { 01001 struct ast_channel *ch; 01002 char *cid_num, *cid_name; 01003 int fmt; 01004 01005 if (!ast_strlen_zero(pvt->options.cid_num)) 01006 cid_num = pvt->options.cid_num; 01007 else 01008 cid_num = pvt->cd.call_source_e164; 01009 01010 if (!ast_strlen_zero(pvt->options.cid_name)) 01011 cid_name = pvt->options.cid_name; 01012 else 01013 cid_name = pvt->cd.call_source_name; 01014 01015 /* Don't hold a oh323_pvt lock while we allocate a chanel */ 01016 ast_mutex_unlock(&pvt->lock); 01017 ch = ast_channel_alloc(1, state, cid_num, cid_name, pvt->accountcode, pvt->exten, pvt->context, pvt->amaflags, "H323/%s", host); 01018 /* Update usage counter */ 01019 ast_module_ref(ast_module_info->self); 01020 ast_mutex_lock(&pvt->lock); 01021 if (ch) { 01022 ch->tech = &oh323_tech; 01023 if (!(fmt = pvt->jointcapability) && !(fmt = pvt->options.capability)) 01024 fmt = global_options.capability; 01025 ch->nativeformats = ast_codec_choose(&pvt->options.prefs, fmt, 1)/* | (pvt->jointcapability & AST_FORMAT_VIDEO_MASK)*/; 01026 pvt->nativeformats = ch->nativeformats; 01027 fmt = ast_best_codec(ch->nativeformats); 01028 ch->writeformat = fmt; 01029 ch->rawwriteformat = fmt; 01030 ch->readformat = fmt; 01031 ch->rawreadformat = fmt; 01032 #if 0 01033 ch->fds[0] = ast_rtp_fd(pvt->rtp); 01034 ch->fds[1] = ast_rtcp_fd(pvt->rtp); 01035 #endif 01036 #ifdef VIDEO_SUPPORT 01037 if (pvt->vrtp) { 01038 ch->fds[2] = ast_rtp_fd(pvt->vrtp); 01039 ch->fds[3] = ast_rtcp_fd(pvt->vrtp); 01040 } 01041 #endif 01042 #ifdef T38_SUPPORT 01043 if (pvt->udptl) { 01044 ch->fds[4] = ast_udptl_fd(pvt->udptl); 01045 } 01046 #endif 01047 if (state == AST_STATE_RING) { 01048 ch->rings = 1; 01049 } 01050 /* Allocate dsp for in-band DTMF support */ 01051 if (pvt->options.dtmfmode & H323_DTMF_INBAND) { 01052 pvt->vad = ast_dsp_new(); 01053 ast_dsp_set_features(pvt->vad, DSP_FEATURE_DTMF_DETECT); 01054 } 01055 /* Register channel functions. */ 01056 ch->tech_pvt = pvt; 01057 /* Set the owner of this channel */ 01058 pvt->owner = ch; 01059 01060 ast_copy_string(ch->context, pvt->context, sizeof(ch->context)); 01061 ast_copy_string(ch->exten, pvt->exten, sizeof(ch->exten)); 01062 ch->priority = 1; 01063 if (!ast_strlen_zero(pvt->accountcode)) { 01064 ast_string_field_set(ch, accountcode, pvt->accountcode); 01065 } 01066 if (pvt->amaflags) { 01067 ch->amaflags = pvt->amaflags; 01068 } 01069 01070 /* Don't use ast_set_callerid() here because it will 01071 * generate a needless NewCallerID event */ 01072 ch->cid.cid_ani = ast_strdup(cid_num); 01073 01074 if (pvt->cd.redirect_reason >= 0) { 01075 ch->cid.cid_rdnis = ast_strdup(pvt->cd.redirect_number); 01076 pbx_builtin_setvar_helper(ch, "PRIREDIRECTREASON", redirectingreason2str(pvt->cd.redirect_reason)); 01077 } 01078 ch->cid.cid_pres = pvt->cd.presentation; 01079 ch->cid.cid_ton = pvt->cd.type_of_number; 01080 01081 if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) { 01082 ch->cid.cid_dnid = strdup(pvt->exten); 01083 } 01084 if (pvt->cd.transfer_capability >= 0) 01085 ch->transfercapability = pvt->cd.transfer_capability; 01086 if (state != AST_STATE_DOWN) { 01087 if (ast_pbx_start(ch)) { 01088 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name); 01089 ast_hangup(ch); 01090 ch = NULL; 01091 } 01092 } 01093 } else { 01094 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 01095 } 01096 return ch; 01097 }
| static int __oh323_rtp_create | ( | struct oh323_pvt * | pvt | ) | [static] |
Definition at line 953 of file chan_h323.c.
References ast_channel_trylock, ast_channel_unlock, ast_find_ourip(), ast_jb_configure(), ast_log(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), ast_rtcp_fd(), ast_rtp_codec_setpref(), ast_rtp_fd(), ast_rtp_new_with_bindaddr(), ast_rtp_set_rtpmap_type(), ast_rtp_setnat(), ast_rtp_settos(), oh323_pvt::dtmf_pt, errno, ast_channel::fds, global_jbconf, io, oh323_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, oh323_pvt::options, oh323_pvt::owner, oh323_pvt::peer_prefs, oh323_pvt::peercapability, oh323_pvt::rtp, sched, and oh323_pvt::update_rtp_info.
Referenced by external_rtp_create(), and setup_rtp_connection().
00954 { 00955 struct in_addr our_addr; 00956 00957 if (pvt->rtp) 00958 return 0; 00959 00960 if (ast_find_ourip(&our_addr, bindaddr)) { 00961 ast_mutex_unlock(&pvt->lock); 00962 ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n"); 00963 return -1; 00964 } 00965 pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, our_addr); 00966 if (!pvt->rtp) { 00967 ast_mutex_unlock(&pvt->lock); 00968 ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno)); 00969 return -1; 00970 } 00971 if (h323debug) 00972 ast_log(LOG_DEBUG, "Created RTP channel\n"); 00973 00974 ast_rtp_settos(pvt->rtp, tos); 00975 00976 if (h323debug) 00977 ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat); 00978 ast_rtp_setnat(pvt->rtp, pvt->options.nat); 00979 00980 if (pvt->dtmf_pt > 0) 00981 ast_rtp_set_rtpmap_type(pvt->rtp, pvt->dtmf_pt, "audio", "telephone-event", 0); 00982 00983 if (pvt->peercapability) 00984 ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs); 00985 00986 if (pvt->owner && !ast_channel_trylock(pvt->owner)) { 00987 ast_jb_configure(pvt->owner, &global_jbconf); 00988 pvt->owner->fds[0] = ast_rtp_fd(pvt->rtp); 00989 pvt->owner->fds[1] = ast_rtcp_fd(pvt->rtp); 00990 ast_queue_frame(pvt->owner, &ast_null_frame); /* Tell Asterisk to apply changes */ 00991 ast_channel_unlock(pvt->owner); 00992 } else 00993 pvt->update_rtp_info = 1; 00994 00995 return 0; 00996 }
| static void __oh323_update_info | ( | struct ast_channel * | c, | |
| struct oh323_pvt * | pvt | |||
| ) | [static] |
Definition at line 339 of file chan_h323.c.
References ast_channel::_softhangup, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_jb_configure(), ast_log(), ast_null_frame, ast_queue_control(), ast_queue_frame(), ast_queue_hangup(), ast_rtcp_fd(), ast_rtp_fd(), ast_sched_add(), AST_SCHED_DEL, ast_set_read_format(), ast_set_write_format(), ast_setstate(), AST_SOFTHANGUP_DEV, oh323_pvt::curDTMF, oh323_pvt::DTMFsched, f, ast_channel::fds, global_jbconf, oh323_pvt::hangupcause, ast_channel::hangupcause, LOG_DEBUG, LOG_DTMF, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::needhangup, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_pvt::newstate, oh323_simulate_dtmf_end(), oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, sched, oh323_pvt::update_rtp_info, and ast_channel::writeformat.
Referenced by oh323_read(), oh323_update_info(), and oh323_write().
00340 { 00341 if (c->nativeformats != pvt->nativeformats) { 00342 if (h323debug) 00343 ast_log(LOG_DEBUG, "Preparing %s for new native format\n", c->name); 00344 c->nativeformats = pvt->nativeformats; 00345 ast_set_read_format(c, c->readformat); 00346 ast_set_write_format(c, c->writeformat); 00347 } 00348 if (pvt->needhangup) { 00349 if (h323debug) 00350 ast_log(LOG_DEBUG, "Process pending hangup for %s\n", c->name); 00351 c->_softhangup |= AST_SOFTHANGUP_DEV; 00352 c->hangupcause = pvt->hangupcause; 00353 ast_queue_hangup(c); 00354 pvt->needhangup = 0; 00355 pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->DTMFsched = -1; 00356 } 00357 if (pvt->newstate >= 0) { 00358 ast_setstate(c, pvt->newstate); 00359 pvt->newstate = -1; 00360 } 00361 if (pvt->newcontrol >= 0) { 00362 ast_queue_control(c, pvt->newcontrol); 00363 pvt->newcontrol = -1; 00364 } 00365 if (pvt->newdigit >= 0) { 00366 struct ast_frame f = { 00367 .frametype = AST_FRAME_DTMF_END, 00368 .subclass = pvt->newdigit, 00369 .samples = pvt->newduration * 8, 00370 .len = pvt->newduration, 00371 .src = "UPDATE_INFO", 00372 }; 00373 if (pvt->newdigit == ' ') { /* signalUpdate message */ 00374 f.subclass = pvt->curDTMF; 00375 if (pvt->DTMFsched >= 0) { 00376 AST_SCHED_DEL(sched, pvt->DTMFsched); 00377 } 00378 } else { /* Regular input or signal message */ 00379 if (pvt->newduration) { /* This is a signal, signalUpdate follows */ 00380 f.frametype = AST_FRAME_DTMF_BEGIN; 00381 AST_SCHED_DEL(sched, pvt->DTMFsched); 00382 pvt->DTMFsched = ast_sched_add(sched, pvt->newduration, oh323_simulate_dtmf_end, pvt); 00383 if (h323debug) 00384 ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", pvt->newduration, pvt->DTMFsched); 00385 } 00386 pvt->curDTMF = pvt->newdigit; 00387 } 00388 ast_queue_frame(c, &f); 00389 pvt->newdigit = -1; 00390 } 00391 if (pvt->update_rtp_info > 0) { 00392 if (pvt->rtp) { 00393 ast_jb_configure(c, &global_jbconf); 00394 c->fds[0] = ast_rtp_fd(pvt->rtp); 00395 c->fds[1] = ast_rtcp_fd(pvt->rtp); 00396 ast_queue_frame(pvt->owner, &ast_null_frame); /* Tell Asterisk to apply changes */ 00397 } 00398 pvt->update_rtp_info = -1; 00399 } 00400 }
| static int answer_call | ( | unsigned | call_reference, | |
| const char * | token | |||
| ) | [static] |
Call-back function to start PBX when OpenH323 ready to serve incoming call
Returns 1 on success
Definition at line 2173 of file chan_h323.c.
References __oh323_new(), AST_CAUSE_UNALLOCATED, ast_exists_extension(), ast_log(), ast_mutex_unlock(), AST_STATE_RINGING, oh323_pvt::cd, oh323_pvt::context, oh323_pvt::exten, find_call_locked(), h323debug, oh323_pvt::lock, LOG_DEBUG, LOG_ERROR, and LOG_NOTICE.
Referenced by load_module().
02174 { 02175 struct oh323_pvt *pvt; 02176 struct ast_channel *c = NULL; 02177 enum {ext_original, ext_s, ext_i, ext_notexists} try_exten; 02178 char tmp_exten[sizeof(pvt->exten)]; 02179 02180 if (h323debug) 02181 ast_log(LOG_DEBUG, "Preparing Asterisk to answer for %s\n", token); 02182 02183 /* Find the call or allocate a private structure if call not found */ 02184 pvt = find_call_locked(call_reference, token); 02185 if (!pvt) { 02186 ast_log(LOG_ERROR, "Something is wrong: answer_call\n"); 02187 return 0; 02188 } 02189 /* Check if requested extension@context pair exists in the dialplan */ 02190 ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten)); 02191 02192 /* Try to find best extension in specified context */ 02193 if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) { 02194 if (tmp_exten[0] == 's') 02195 try_exten = ext_s; 02196 else if (tmp_exten[0] == 'i') 02197 try_exten = ext_i; 02198 else 02199 try_exten = ext_original; 02200 } else 02201 try_exten = ext_original; 02202 do { 02203 if (ast_exists_extension(NULL, pvt->context, tmp_exten, 1, NULL)) 02204 break; 02205 switch (try_exten) { 02206 case ext_original: 02207 tmp_exten[0] = 's'; 02208 tmp_exten[1] = '\0'; 02209 try_exten = ext_s; 02210 break; 02211 case ext_s: 02212 tmp_exten[0] = 'i'; 02213 try_exten = ext_i; 02214 break; 02215 case ext_i: 02216 try_exten = ext_notexists; 02217 break; 02218 default: 02219 break; 02220 } 02221 } while (try_exten != ext_notexists); 02222 02223 /* Drop the call if we don't have <exten>, s and i extensions */ 02224 if (try_exten == ext_notexists) { 02225 ast_log(LOG_NOTICE, "Dropping call because extensions '%s', 's' and 'i' doesn't exists in context [%s]\n", pvt->exten, pvt->context); 02226 ast_mutex_unlock(&pvt->lock); 02227 h323_clear_call(token, AST_CAUSE_UNALLOCATED); 02228 return 0; 02229 } else if ((try_exten != ext_original) && (strcmp(pvt->exten, tmp_exten) != 0)) { 02230 if (h323debug) 02231 ast_log(LOG_DEBUG, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context); 02232 ast_copy_string(pvt->exten, tmp_exten, sizeof(pvt->exten)); 02233 } 02234 02235 /* allocate a channel and tell asterisk about it */ 02236 c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token); 02237 02238 /* And release when done */ 02239 ast_mutex_unlock(&pvt->lock); 02240 if (!c) { 02241 ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n"); 02242 return 0; 02243 } 02244 return 1; 02245 }
| AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
| AST_MODFLAG_DEFAULT | , | |||
| "The NuFone Network's OpenH323 Channel Driver" | , | |||
| . | load = load_module, |
|||
| . | unload = unload_module, |
|||
| . | reload = reload | |||
| ) |
| AST_MUTEX_DEFINE_STATIC | ( | h323_reload_lock | ) |
| AST_MUTEX_DEFINE_STATIC | ( | caplock | ) |
| AST_MUTEX_DEFINE_STATIC | ( | monlock | ) |
| AST_MUTEX_DEFINE_STATIC | ( | iflock | ) |
Protect the interface list (oh323_pvt)
| static struct oh323_alias* build_alias | ( | const char * | name, | |
| struct ast_variable * | v, | |||
| struct ast_variable * | alt, | |||
| int | realtime | |||
| ) | [static] |
Definition at line 1190 of file chan_h323.c.
References aliasl, ast_log(), ASTOBJ_CONTAINER_FIND_UNLINK_FULL, ASTOBJ_INIT, ASTOBJ_UNMARK, calloc, LOG_WARNING, ast_variable::name, ast_variable::next, and ast_variable::value.
01191 { 01192 struct oh323_alias *alias; 01193 int found = 0; 01194 01195 alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&aliasl, name, name, 0, 0, strcasecmp); 01196 01197 if (alias) 01198 found++; 01199 else { 01200 if (!(alias = (struct oh323_alias *)calloc(1, sizeof(*alias)))) 01201 return NULL; 01202 ASTOBJ_INIT(alias); 01203 } 01204 if (!found && name) 01205 ast_copy_string(alias->name, name, sizeof(alias->name)); 01206 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) { 01207 if (!strcasecmp(v->name, "e164")) { 01208 ast_copy_string(alias->e164, v->value, sizeof(alias->e164)); 01209 } else if (!strcasecmp(v->name, "prefix")) { 01210 ast_copy_string(alias->prefix, v->value, sizeof(alias->prefix)); 01211 } else if (!strcasecmp(v->name, "context")) { 01212 ast_copy_string(alias->context, v->value, sizeof(alias->context)); 01213 } else if (!strcasecmp(v->name, "secret")) { 01214 ast_copy_string(alias->secret, v->