![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
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 * \author Jeremy McNamara 00029 * 00030 * \par See also 00031 * \arg Config_h323 00032 * 00033 * \ingroup channel_drivers 00034 */ 00035 00036 /*** MODULEINFO 00037 <depend>openh323</depend> 00038 <defaultenabled>no</defaultenabled> 00039 ***/ 00040 00041 #ifdef __cplusplus 00042 extern "C" { 00043 #endif 00044 00045 #include "asterisk.h" 00046 00047 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 51637 $") 00048 00049 #ifdef __cplusplus 00050 } 00051 #endif 00052 00053 #include <sys/socket.h> 00054 #include <sys/signal.h> 00055 #include <sys/param.h> 00056 #if defined(BSD) 00057 #ifndef IPTOS_MINCOST 00058 #define IPTOS_MINCOST 0x02 00059 #endif 00060 #endif 00061 #include <arpa/inet.h> 00062 #include <net/if.h> 00063 #include <netinet/in.h> 00064 #include <netinet/in_systm.h> 00065 #include <netinet/ip.h> 00066 #include <unistd.h> 00067 #include <stdlib.h> 00068 #include <netdb.h> 00069 #include <stdio.h> 00070 #include <string.h> 00071 #include <errno.h> 00072 #include <fcntl.h> 00073 00074 #ifdef __cplusplus 00075 extern "C" { 00076 #endif 00077 00078 #include "asterisk/lock.h" 00079 #include "asterisk/logger.h" 00080 #include "asterisk/channel.h" 00081 #include "asterisk/config.h" 00082 #include "asterisk/module.h" 00083 #include "asterisk/musiconhold.h" 00084 #include "asterisk/pbx.h" 00085 #include "asterisk/options.h" 00086 #include "asterisk/utils.h" 00087 #include "asterisk/lock.h" 00088 #include "asterisk/sched.h" 00089 #include "asterisk/io.h" 00090 #include "asterisk/rtp.h" 00091 #include "asterisk/acl.h" 00092 #include "asterisk/callerid.h" 00093 #include "asterisk/cli.h" 00094 #include "asterisk/dsp.h" 00095 #include "asterisk/causes.h" 00096 #include "asterisk/stringfields.h" 00097 #include "asterisk/abstract_jb.h" 00098 #include "asterisk/astobj.h" 00099 00100 #ifdef __cplusplus 00101 } 00102 #endif 00103 00104 #include "h323/chan_h323.h" 00105 00106 receive_digit_cb on_receive_digit; 00107 on_rtp_cb on_external_rtp_create; 00108 start_rtp_cb on_start_rtp_channel; 00109 setup_incoming_cb on_incoming_call; 00110 setup_outbound_cb on_outgoing_call; 00111 chan_ringing_cb on_chan_ringing; 00112 con_established_cb on_connection_established; 00113 clear_con_cb on_connection_cleared; 00114 answer_call_cb on_answer_call; 00115 progress_cb on_progress; 00116 rfc2833_cb on_set_rfc2833_payload; 00117 hangup_cb on_hangup; 00118 setcapabilities_cb on_setcapabilities; 00119 setpeercapabilities_cb on_setpeercapabilities; 00120 onhold_cb on_hold; 00121 00122 /* global debug flag */ 00123 int h323debug; 00124 00125 /*! Global jitterbuffer configuration - by default, jb is disabled */ 00126 static struct ast_jb_conf default_jbconf = 00127 { 00128 .flags = 0, 00129 .max_size = -1, 00130 .resync_threshold = -1, 00131 .impl = "" 00132 }; 00133 static struct ast_jb_conf global_jbconf; 00134 00135 /** Variables required by Asterisk */ 00136 static const char tdesc[] = "The NuFone Network's Open H.323 Channel Driver"; 00137 static const char config[] = "h323.conf"; 00138 static char default_context[AST_MAX_CONTEXT] = "default"; 00139 static struct sockaddr_in bindaddr; 00140 00141 #define GLOBAL_CAPABILITY (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_G726_AAL2 | AST_FORMAT_H261) 00142 00143 /** H.323 configuration values */ 00144 static int h323_signalling_port = 1720; 00145 static char gatekeeper[100]; 00146 static int gatekeeper_disable = 1; 00147 static int gatekeeper_discover = 0; 00148 static int gkroute = 0; 00149 /* Find user by alias (h.323 id) is default, alternative is the incomming call's source IP address*/ 00150 static int userbyalias = 1; 00151 static int acceptAnonymous = 1; 00152 static int tos = 0; 00153 static char secret[50]; 00154 static unsigned int unique = 0; 00155 00156 static call_options_t global_options; 00157 00158 /** Private structure of a OpenH323 channel */ 00159 struct oh323_pvt { 00160 ast_mutex_t lock; /* Channel private lock */ 00161 call_options_t options; /* Options to be used during call setup */ 00162 int alreadygone; /* Whether or not we've already been destroyed by our peer */ 00163 int needdestroy; /* if we need to be destroyed */ 00164 call_details_t cd; /* Call details */ 00165 struct ast_channel *owner; /* Who owns us */ 00166 struct sockaddr_in sa; /* Our peer */ 00167 struct sockaddr_in redirip; /* Where our RTP should be going if not to us */ 00168 int nonCodecCapability; /* non-audio capability */ 00169 int outgoing; /* Outgoing or incoming call? */ 00170 char exten[AST_MAX_EXTENSION]; /* Requested extension */ 00171 char context[AST_MAX_CONTEXT]; /* Context where to start */ 00172 char accountcode[256]; /* Account code */ 00173 char rdnis[80]; /* Referring DNIS, if available */ 00174 int amaflags; /* AMA Flags */ 00175 struct ast_rtp *rtp; /* RTP Session */ 00176 struct ast_dsp *vad; /* Used for in-band DTMF detection */ 00177 int nativeformats; /* Codec formats supported by a channel */ 00178 int needhangup; /* Send hangup when Asterisk is ready */ 00179 int hangupcause; /* Hangup cause from OpenH323 layer */ 00180 int newstate; /* Pending state change */ 00181 int newcontrol; /* Pending control to send */ 00182 int newdigit; /* Pending DTMF digit to send */ 00183 int newduration; /* Pending DTMF digit duration to send */ 00184 int pref_codec; /* Preferred codec */ 00185 int peercapability; /* Capabilities learned from peer */ 00186 int jointcapability; /* Common capabilities for local and remote side */ 00187 struct ast_codec_pref peer_prefs; /* Preferenced list of codecs which remote side supports */ 00188 int dtmf_pt[2]; /* Payload code used for RFC2833/CISCO messages */ 00189 int curDTMF; /* DTMF tone being generated to Asterisk side */ 00190 int DTMFsched; /* Scheduler descriptor for DTMF */ 00191 int update_rtp_info; /* Configuration of fd's array is pending */ 00192 int recvonly; /* Peer isn't wish to receive our voice stream */ 00193 int txDtmfDigit; /* DTMF digit being to send to H.323 side */ 00194 int noInbandDtmf; /* Inband DTMF processing by DSP isn't available */ 00195 int connection_established; /* Call got CONNECT message */ 00196 int got_progress; /* Call got PROGRESS message, pass inband audio */ 00197 struct oh323_pvt *next; /* Next channel in list */ 00198 } *iflist = NULL; 00199 00200 static struct ast_user_list { 00201 ASTOBJ_CONTAINER_COMPONENTS(struct oh323_user); 00202 } userl; 00203 00204 static struct ast_peer_list { 00205 ASTOBJ_CONTAINER_COMPONENTS(struct oh323_peer); 00206 } peerl; 00207 00208 static struct ast_alias_list { 00209 ASTOBJ_CONTAINER_COMPONENTS(struct oh323_alias); 00210 } aliasl; 00211 00212 /** Asterisk RTP stuff */ 00213 static struct sched_context *sched; 00214 static struct io_context *io; 00215 00216 /** Protect the interface list (oh323_pvt) */ 00217 AST_MUTEX_DEFINE_STATIC(iflock); 00218 00219 /* Protect the monitoring thread, so only one process can kill or start it, and not 00220 when it's doing something critical. */ 00221 AST_MUTEX_DEFINE_STATIC(monlock); 00222 00223 /* Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack. */ 00224 AST_MUTEX_DEFINE_STATIC(caplock); 00225 00226 /* Protect the reload process */ 00227 AST_MUTEX_DEFINE_STATIC(h323_reload_lock); 00228 static int h323_reloading = 0; 00229 00230 /* This is the thread for the monitor which checks for input on the channels 00231 which are not currently in use. */ 00232 static pthread_t monitor_thread = AST_PTHREADT_NULL; 00233 static int restart_monitor(void); 00234 static int h323_do_reload(void); 00235 00236 static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause); 00237 static int oh323_digit_begin(struct ast_channel *c, char digit); 00238 static int oh323_digit_end(struct ast_channel *c, char digit, unsigned int duration); 00239 static int oh323_call(struct ast_channel *c, char *dest, int timeout); 00240 static int oh323_hangup(struct ast_channel *c); 00241 static int oh323_answer(struct ast_channel *c); 00242 static struct ast_frame *oh323_read(struct ast_channel *c); 00243 static int oh323_write(struct ast_channel *c, struct ast_frame *frame); 00244 static int oh323_indicate(struct ast_channel *c, int condition, const void *data, size_t datalen); 00245 static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan); 00246 00247 static const struct ast_channel_tech oh323_tech = { 00248 .type = "H323", 00249 .description = tdesc, 00250 .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1), 00251 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER, 00252 .requester = oh323_request, 00253 .send_digit_begin = oh323_digit_begin, 00254 .send_digit_end = oh323_digit_end, 00255 .call = oh323_call, 00256 .hangup = oh323_hangup, 00257 .answer = oh323_answer, 00258 .read = oh323_read, 00259 .write = oh323_write, 00260 .indicate = oh323_indicate, 00261 .fixup = oh323_fixup, 00262 /* disable, for now */ 00263 #if 0 00264 .bridge = ast_rtp_bridge, 00265 #endif 00266 }; 00267 00268 static const char* redirectingreason2str(int redirectingreason) 00269 { 00270 switch (redirectingreason) { 00271 case 0: 00272 return "UNKNOWN"; 00273 case 1: 00274 return "BUSY"; 00275 case 2: 00276 return "NO_REPLY"; 00277 case 0xF: 00278 return "UNCONDITIONAL"; 00279 default: 00280 return "NOREDIRECT"; 00281 } 00282 } 00283 00284 static void oh323_destroy_alias(struct oh323_alias *alias) 00285 { 00286 if (h323debug) 00287 ast_log(LOG_DEBUG, "Destroying alias '%s'\n", alias->name); 00288 free(alias); 00289 } 00290 00291 static void oh323_destroy_user(struct oh323_user *user) 00292 { 00293 if (h323debug) 00294 ast_log(LOG_DEBUG, "Destroying user '%s'\n", user->name); 00295 ast_free_ha(user->ha); 00296 free(user); 00297 } 00298 00299 static void oh323_destroy_peer(struct oh323_peer *peer) 00300 { 00301 if (h323debug) 00302 ast_log(LOG_DEBUG, "Destroying peer '%s'\n", peer->name); 00303 ast_free_ha(peer->ha); 00304 free(peer); 00305 } 00306 00307 static int oh323_simulate_dtmf_end(void *data) 00308 { 00309 struct oh323_pvt *pvt = data; 00310 00311 if (pvt) { 00312 ast_mutex_lock(&pvt->lock); 00313 /* Don't hold pvt lock while trying to lock the channel */ 00314 while(pvt->owner && ast_channel_trylock(pvt->owner)) { 00315 ast_mutex_unlock(&pvt->lock); 00316 usleep(1); 00317 ast_mutex_lock(&pvt->lock); 00318 } 00319 00320 if (pvt->owner) { 00321 struct ast_frame f = { 00322 .frametype = AST_FRAME_DTMF_END, 00323 .subclass = pvt->curDTMF, 00324 .samples = 0, 00325 .src = "SIMULATE_DTMF_END", 00326 }; 00327 ast_queue_frame(pvt->owner, &f); 00328 ast_channel_unlock(pvt->owner); 00329 } 00330 00331 pvt->DTMFsched = -1; 00332 ast_mutex_unlock(&pvt->lock); 00333 } 00334 00335 return 0; 00336 } 00337 00338 /* Channel and private structures should be already locked */ 00339 static void __oh323_update_info(struct ast_channel *c, struct oh323_pvt *pvt) 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 .src = "UPDATE_INFO", 00371 }; 00372 if (pvt->newdigit == ' ') { /* signalUpdate message */ 00373 f.subclass = pvt->curDTMF; 00374 if (pvt->DTMFsched >= 0) { 00375 ast_sched_del(sched, pvt->DTMFsched); 00376 pvt->DTMFsched = -1; 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 if (pvt->DTMFsched >= 0) 00382 ast_sched_del(sched, pvt->DTMFsched); 00383 pvt->DTMFsched = ast_sched_add(sched, pvt->newduration, oh323_simulate_dtmf_end, pvt); 00384 if (h323debug) 00385 ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", pvt->newduration, pvt->DTMFsched); 00386 } 00387 pvt->curDTMF = pvt->newdigit; 00388 } 00389 ast_queue_frame(c, &f); 00390 pvt->newdigit = -1; 00391 } 00392 if (pvt->update_rtp_info > 0) { 00393 if (pvt->rtp) { 00394 ast_jb_configure(c, &global_jbconf); 00395 c->fds[0] = ast_rtp_fd(pvt->rtp); 00396 c->fds[1] = ast_rtcp_fd(pvt->rtp); 00397 ast_queue_frame(pvt->owner, &ast_null_frame); /* Tell Asterisk to apply changes */ 00398 } 00399 pvt->update_rtp_info = -1; 00400 } 00401 } 00402 00403 /* Only channel structure should be locked */ 00404 static void oh323_update_info(struct ast_channel *c) 00405 { 00406 struct oh323_pvt *pvt = c->tech_pvt; 00407 00408 if (pvt) { 00409 ast_mutex_lock(&pvt->lock); 00410 __oh323_update_info(c, pvt); 00411 ast_mutex_unlock(&pvt->lock); 00412 } 00413 } 00414 00415 static void cleanup_call_details(call_details_t *cd) 00416 { 00417 if (cd->call_token) { 00418 free(cd->call_token); 00419 cd->call_token = NULL; 00420 } 00421 if (cd->call_source_aliases) { 00422 free(cd->call_source_aliases); 00423 cd->call_source_aliases = NULL; 00424 } 00425 if (cd->call_dest_alias) { 00426 free(cd->call_dest_alias); 00427 cd->call_dest_alias = NULL; 00428 } 00429 if (cd->call_source_name) { 00430 free(cd->call_source_name); 00431 cd->call_source_name = NULL; 00432 } 00433 if (cd->call_source_e164) { 00434 free(cd->call_source_e164); 00435 cd->call_source_e164 = NULL; 00436 } 00437 if (cd->call_dest_e164) { 00438 free(cd->call_dest_e164); 00439 cd->call_dest_e164 = NULL; 00440 } 00441 if (cd->sourceIp) { 00442 free(cd->sourceIp); 00443 cd->sourceIp = NULL; 00444 } 00445 if (cd->redirect_number) { 00446 free(cd->redirect_number); 00447 cd->redirect_number = NULL; 00448 } 00449 } 00450 00451 static void __oh323_destroy(struct oh323_pvt *pvt) 00452 { 00453 struct oh323_pvt *cur, *prev = NULL; 00454 00455 if (pvt->DTMFsched >= 0) { 00456 ast_sched_del(sched, pvt->DTMFsched); 00457 pvt->DTMFsched = -1; 00458 } 00459 00460 if (pvt->rtp) { 00461 ast_rtp_destroy(pvt->rtp); 00462 } 00463 00464 /* Free dsp used for in-band DTMF detection */ 00465 if (pvt->vad) { 00466 ast_dsp_free(pvt->vad); 00467 } 00468 cleanup_call_details(&pvt->cd); 00469 00470 /* Unlink us from the owner if we have one */ 00471 if (pvt->owner) { 00472 ast_channel_lock(pvt->owner); 00473 if (h323debug) 00474 ast_log(LOG_DEBUG, "Detaching from %s\n", pvt->owner->name); 00475 pvt->owner->tech_pvt = NULL; 00476 ast_channel_unlock(pvt->owner); 00477 } 00478 cur = iflist; 00479 while(cur) { 00480 if (cur == pvt) { 00481 if (prev) 00482 prev->next = cur->next; 00483 else 00484 iflist = cur->next; 00485 break; 00486 } 00487 prev = cur; 00488 cur = cur->next; 00489 } 00490 if (!cur) { 00491 ast_log(LOG_WARNING, "%p is not in list?!?! \n", cur); 00492 } else { 00493 ast_mutex_unlock(&pvt->lock); 00494 ast_mutex_destroy(&pvt->lock); 00495 free(pvt); 00496 } 00497 } 00498 00499 static void oh323_destroy(struct oh323_pvt *pvt) 00500 { 00501 if (h323debug) { 00502 ast_log(LOG_DEBUG, "Destroying channel %s\n", (pvt->owner ? pvt->owner->name : "<unknown>")); 00503 } 00504 ast_mutex_lock(&iflock); 00505 ast_mutex_lock(&pvt->lock); 00506 __oh323_destroy(pvt); 00507 ast_mutex_unlock(&iflock); 00508 } 00509 00510 static int oh323_digit_begin(struct ast_channel *c, char digit) 00511 { 00512 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt; 00513 char *token; 00514 00515 if (!pvt) { 00516 ast_log(LOG_ERROR, "No private structure?! This is bad\n"); 00517 return -1; 00518 } 00519 ast_mutex_lock(&pvt->lock); 00520 if (pvt->rtp && 00521 (((pvt->options.dtmfmode & H323_DTMF_RFC2833) && pvt->dtmf_pt[0]) 00522 /*|| ((pvt->options.dtmfmode & H323_DTMF_CISCO) && pvt->dtmf_pt[1]))*/)) { 00523 /* out-of-band DTMF */ 00524 if (h323debug) { 00525 ast_log(LOG_DTMF, "Begin sending out-of-band digit %c on %s\n", digit, c->name); 00526 } 00527 ast_rtp_senddigit_begin(pvt->rtp, digit); 00528 ast_mutex_unlock(&pvt->lock); 00529 } else if (pvt->txDtmfDigit != digit) { 00530 /* in-band DTMF */ 00531 if (h323debug) { 00532 ast_log(LOG_DTMF, "Begin sending inband digit %c on %s\n", digit, c->name); 00533 } 00534 pvt->txDtmfDigit = digit; 00535 token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL; 00536 ast_mutex_unlock(&pvt->lock); 00537 h323_send_tone(token, digit); 00538 if (token) { 00539 free(token); 00540 } 00541 } else 00542 ast_mutex_unlock(&pvt->lock); 00543 oh323_update_info(c); 00544 return 0; 00545 } 00546 00547 /** 00548 * Send (play) the specified digit to the channel. 00549 * 00550 */ 00551 static int oh323_digit_end(struct ast_channel *c, char digit, unsigned int duration) 00552 { 00553 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt; 00554 char *token; 00555 00556 if (!pvt) { 00557 ast_log(LOG_ERROR, "No private structure?! This is bad\n"); 00558 return -1; 00559 } 00560 ast_mutex_lock(&pvt->lock); 00561 if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833) && ((pvt->dtmf_pt[0] > 0) || (pvt->dtmf_pt[0] > 0))) { 00562 /* out-of-band DTMF */ 00563 if (h323debug) { 00564 ast_log(LOG_DTMF, "End sending out-of-band digit %c on %s\n", digit, c->name); 00565 } 00566 ast_rtp_senddigit_end(pvt->rtp, digit); 00567 ast_mutex_unlock(&pvt->lock); 00568 } else { 00569 /* in-band DTMF */ 00570 if (h323debug) { 00571 ast_log(LOG_DTMF, "End sending inband digit %c on %s\n", digit, c->name); 00572 } 00573 pvt->txDtmfDigit = ' '; 00574 token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL; 00575 ast_mutex_unlock(&pvt->lock); 00576 h323_send_tone(token, ' '); 00577 if (token) { 00578 free(token); 00579 } 00580 } 00581 oh323_update_info(c); 00582 return 0; 00583 } 00584 00585 /** 00586 * Make a call over the specified channel to the specified 00587 * destination. 00588 * Returns -1 on error, 0 on success. 00589 */ 00590 static int oh323_call(struct ast_channel *c, char *dest, int timeout) 00591 { 00592 int res = 0; 00593 struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt; 00594 const char *addr; 00595 char called_addr[1024]; 00596 00597 if (h323debug) { 00598 ast_log(LOG_DEBUG, "Calling to %s on %s\n", dest, c->name); 00599 } 00600 if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) { 00601 ast_log(LOG_WARNING, "Line is already in use (%s)\n", c->name); 00602 return -1; 00603 } 00604 ast_mutex_lock(&pvt->lock); 00605 if (!gatekeeper_disable) { 00606 if (ast_strlen_zero(pvt->exten)) { 00607 ast_copy_string(called_addr, dest, sizeof(called_addr)); 00608 } else { 00609 snprintf(called_addr, sizeof(called_addr), "%s@%s", pvt->exten, dest); 00610 } 00611 } else { 00612 res = htons(pvt->sa.sin_port); 00613 addr = ast_inet_ntoa(pvt->sa.sin_addr); 00614 if (ast_strlen_zero(pvt->exten)) { 00615 snprintf(called_addr, sizeof(called_addr), "%s:%d", addr, res); 00616 } else { 00617 snprintf(called_addr, sizeof(called_addr), "%s@%s:%d", pvt->exten, addr, res); 00618 } 00619 } 00620 /* make sure null terminated */ 00621 called_addr[sizeof(called_addr) - 1] = '\0'; 00622 00623 if (c->cid.cid_num) 00624 ast_copy_string(pvt->options.cid_num, c->cid.cid_num, sizeof(pvt->options.cid_num)); 00625 00626 if (c->cid.cid_name) 00627 ast_copy_string(pvt->options.cid_name, c->cid.cid_name, sizeof(pvt->options.cid_name)); 00628 00629 if (c->cid.cid_rdnis) { 00630 ast_copy_string(pvt->options.cid_rdnis, c->cid.cid_rdnis, sizeof(pvt->options.cid_rdnis)); 00631 } 00632 00633 pvt->options.presentation = c->cid.cid_pres; 00634 pvt->options.type_of_number = c->cid.cid_ton; 00635 00636 if ((addr = pbx_builtin_getvar_helper(c, "PRIREDIRECTREASON"))) { 00637 if (!strcasecmp(addr, "UNKNOWN")) 00638 pvt->options.redirect_reason = 0; 00639 else if (!strcasecmp(addr, "BUSY")) 00640 pvt->options.redirect_reason = 1; 00641 else if (!strcasecmp(addr, "NO_REPLY")) 00642 pvt->options.redirect_reason = 2; 00643 else if (!strcasecmp(addr, "UNCONDITIONAL")) 00644 pvt->options.redirect_reason = 15; 00645 else 00646 pvt->options.redirect_reason = -1; 00647 } else 00648 pvt->options.redirect_reason = -1; 00649 00650 pvt->options.transfer_capability = c->transfercapability; 00651 00652 /* indicate that this is an outgoing call */ 00653 pvt->outgoing = 1; 00654 00655 if (option_verbose > 2) 00656 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", c->transfercapability, ast_transfercapability2str(c->transfercapability)); 00657 if (h323debug) 00658 ast_log(LOG_DEBUG, "Placing outgoing call to %s, %d/%d\n", called_addr, pvt->options.dtmfcodec[0], pvt->options.dtmfcodec[1]); 00659 ast_mutex_unlock(&pvt->lock); 00660 res = h323_make_call(called_addr, &(pvt->cd), &pvt->options); 00661 if (res) { 00662 ast_log(LOG_NOTICE, "h323_make_call failed(%s)\n", c->name); 00663 return -1; 00664 } 00665 oh323_update_info(c); 00666 return 0; 00667 } 00668 00669 static int oh323_answer(struct ast_channel *c) 00670 { 00671 int res; 00672 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt; 00673 char *token; 00674 00675 if (h323debug) 00676 ast_log(LOG_DEBUG, "Answering on %s\n", c->name); 00677 00678 ast_mutex_lock(&pvt->lock); 00679 token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL; 00680 ast_mutex_unlock(&pvt->lock); 00681 res = h323_answering_call(token, 0); 00682 if (token) 00683 free(token); 00684 00685 oh323_update_info(c); 00686 if (c->_state != AST_STATE_UP) { 00687 ast_setstate(c, AST_STATE_UP); 00688 } 00689 return res; 00690 } 00691 00692 static int oh323_hangup(struct ast_channel *c) 00693 { 00694 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt; 00695 int q931cause = AST_CAUSE_NORMAL_CLEARING; 00696 char *call_token; 00697 00698 00699 if (h323debug) 00700 ast_log(LOG_DEBUG, "Hanging up and scheduling destroy of call %s\n", c->name); 00701 00702 if (!c->tech_pvt) { 00703 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 00704 return 0; 00705 } 00706 ast_mutex_lock(&pvt->lock); 00707 /* Determine how to disconnect */ 00708 if (pvt->owner != c) { 00709 ast_log(LOG_WARNING, "Huh? We aren't the owner?\n"); 00710 ast_mutex_unlock(&pvt->lock); 00711 return 0; 00712 } 00713 00714 pvt->owner = NULL; 00715 c->tech_pvt = NULL; 00716 00717 if (c->hangupcause) { 00718 q931cause = c->hangupcause; 00719 } else { 00720 const char *cause = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 00721 if (cause) { 00722 if (!strcmp(cause, "CONGESTION")) { 00723 q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION; 00724 } else if (!strcmp(cause, "BUSY")) { 00725 q931cause = AST_CAUSE_USER_BUSY; 00726 } else if (!strcmp(cause, "CHANISUNVAIL")) { 00727 q931cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL; 00728 } else if (!strcmp(cause, "NOANSWER")) { 00729 q931cause = AST_CAUSE_NO_ANSWER; 00730 } else if (!strcmp(cause, "CANCEL")) { 00731 q931cause = AST_CAUSE_CALL_REJECTED; 00732 } 00733 } 00734 } 00735 00736 /* Start the process if it's not already started */ 00737 if (!pvt->alreadygone && !pvt->hangupcause) { 00738 call_token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL; 00739 if (call_token) { 00740 /* Release lock to eliminate deadlock */ 00741 ast_mutex_unlock(&pvt->lock); 00742 if (h323_clear_call(call_token, q931cause)) { 00743 ast_log(LOG_WARNING, "ClearCall failed.\n"); 00744 } 00745 free(call_token); 00746 ast_mutex_lock(&pvt->lock); 00747 } 00748 } 00749 pvt->needdestroy = 1; 00750 ast_mutex_unlock(&pvt->lock); 00751 00752 /* Update usage counter */ 00753 ast_module_unref(ast_module_info->self); 00754 00755 return 0; 00756 } 00757 00758 static struct ast_frame *oh323_rtp_read(struct oh323_pvt *pvt) 00759 { 00760 /* Retrieve audio/etc from channel. Assumes pvt->lock is already held. */ 00761 struct ast_frame *f; 00762 00763 /* Only apply it for the first packet, we just need the correct ip/port */ 00764 if (pvt->options.nat) { 00765 ast_rtp_setnat(pvt->rtp, pvt->options.nat); 00766 pvt->options.nat = 0; 00767 } 00768 00769 f = ast_rtp_read(pvt->rtp); 00770 /* Don't send RFC2833 if we're not supposed to */ 00771 if (f && (f->frametype == AST_FRAME_DTMF) && !(pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO))) { 00772 return &ast_null_frame; 00773 } 00774 if (pvt->owner) { 00775 /* We already hold the channel lock */ 00776 if (f->frametype == AST_FRAME_VOICE) { 00777 if (f->subclass != pvt->owner->nativeformats) { 00778 /* Try to avoid deadlock */ 00779 if (ast_channel_trylock(pvt->owner)) { 00780 ast_log(LOG_NOTICE, "Format changed but channel is locked. Ignoring frame...\n"); 00781 return &ast_null_frame; 00782 } 00783 if (h323debug) 00784 ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass); 00785 pvt->owner->nativeformats = f->subclass; 00786 pvt->nativeformats = f->subclass; 00787 ast_set_read_format(pvt->owner, pvt->owner->readformat); 00788 ast_set_write_format(pvt->owner, pvt->owner->writeformat); 00789 ast_channel_unlock(pvt->owner); 00790 } 00791 /* Do in-band DTMF detection */ 00792 if ((pvt->options.dtmfmode & H323_DTMF_INBAND) && pvt->vad) { 00793 if ((pvt->nativeformats & (AST_FORMAT_SLINEAR | AST_FORMAT_ALAW | AST_FORMAT_ULAW))) { 00794 if (!ast_channel_trylock(pvt->owner)) { 00795 f = ast_dsp_process(pvt->owner, pvt->vad, f); 00796 ast_channel_unlock(pvt->owner); 00797 } 00798 else 00799 ast_log(LOG_NOTICE, "Unable to process inband DTMF while channel is locked\n"); 00800 } else if (pvt->nativeformats && !pvt->noInbandDtmf) { 00801 ast_log(LOG_NOTICE, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(f->subclass)); 00802 pvt->noInbandDtmf = 1; 00803 } 00804 if (f &&(f->frametype == AST_FRAME_DTMF)) { 00805 if (h323debug) 00806 ast_log(LOG_DTMF, "Received in-band digit %c.\n", f->subclass); 00807 } 00808 } 00809 } 00810 } 00811 return f; 00812 } 00813 00814 static struct ast_frame *oh323_read(struct ast_channel *c) 00815 { 00816 struct ast_frame *fr; 00817 struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt; 00818 ast_mutex_lock(&pvt->lock); 00819 __oh323_update_info(c, pvt); 00820 switch(c->fdno) { 00821 case 0: 00822 fr = oh323_rtp_read(pvt); 00823 break; 00824 case 1: 00825 if (pvt->rtp) 00826 fr = ast_rtcp_read(pvt->rtp); 00827 else 00828 fr = &ast_null_frame; 00829 break; 00830 default: 00831 ast_log(LOG_ERROR, "Unable to handle fd %d on channel %s\n", c->fdno, c->name); 00832 fr = &ast_null_frame; 00833 break; 00834 } 00835 ast_mutex_unlock(&pvt->lock); 00836 return fr; 00837 } 00838 00839 static int oh323_write(struct ast_channel *c, struct ast_frame *frame) 00840 { 00841 struct