00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #ifdef __cplusplus
00042 extern "C" {
00043 #endif
00044
00045 #include "asterisk.h"
00046
00047 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 273793 $")
00048
00049 #ifdef __cplusplus
00050 }
00051 #endif
00052
00053 #include <sys/types.h>
00054 #include <sys/socket.h>
00055 #include <sys/signal.h>
00056 #include <sys/param.h>
00057 #if defined(BSD) || defined(SOLARIS)
00058 #ifndef IPTOS_MINCOST
00059 #define IPTOS_MINCOST 0x02
00060 #endif
00061 #endif
00062 #include <arpa/inet.h>
00063 #include <net/if.h>
00064 #include <netinet/in.h>
00065 #include <netinet/in_systm.h>
00066 #include <netinet/ip.h>
00067 #include <unistd.h>
00068 #include <stdlib.h>
00069 #include <netdb.h>
00070 #include <stdio.h>
00071 #include <string.h>
00072 #include <errno.h>
00073 #include <fcntl.h>
00074
00075 #ifdef __cplusplus
00076 extern "C" {
00077 #endif
00078
00079 #include "asterisk/lock.h"
00080 #include "asterisk/logger.h"
00081 #include "asterisk/channel.h"
00082 #include "asterisk/config.h"
00083 #include "asterisk/module.h"
00084 #include "asterisk/musiconhold.h"
00085 #include "asterisk/pbx.h"
00086 #include "asterisk/options.h"
00087 #include "asterisk/utils.h"
00088 #include "asterisk/lock.h"
00089 #include "asterisk/sched.h"
00090 #include "asterisk/io.h"
00091 #include "asterisk/rtp.h"
00092 #include "asterisk/acl.h"
00093 #include "asterisk/callerid.h"
00094 #include "asterisk/cli.h"
00095 #include "asterisk/dsp.h"
00096 #include "asterisk/causes.h"
00097 #include "asterisk/stringfields.h"
00098 #include "asterisk/abstract_jb.h"
00099 #include "asterisk/astobj.h"
00100
00101 #ifdef __cplusplus
00102 }
00103 #endif
00104
00105 #undef open
00106 #undef close
00107 #include "h323/chan_h323.h"
00108
00109 receive_digit_cb on_receive_digit;
00110 on_rtp_cb on_external_rtp_create;
00111 start_rtp_cb on_start_rtp_channel;
00112 setup_incoming_cb on_incoming_call;
00113 setup_outbound_cb on_outgoing_call;
00114 chan_ringing_cb on_chan_ringing;
00115 con_established_cb on_connection_established;
00116 clear_con_cb on_connection_cleared;
00117 answer_call_cb on_answer_call;
00118 progress_cb on_progress;
00119 rfc2833_cb on_set_rfc2833_payload;
00120 hangup_cb on_hangup;
00121 setcapabilities_cb on_setcapabilities;
00122 setpeercapabilities_cb on_setpeercapabilities;
00123
00124
00125 int h323debug;
00126
00127
00128 static struct ast_jb_conf default_jbconf =
00129 {
00130 .flags = 0,
00131 .max_size = -1,
00132 .resync_threshold = -1,
00133 .impl = ""
00134 };
00135 static struct ast_jb_conf global_jbconf;
00136
00137
00138 static const char tdesc[] = "The NuFone Network's Open H.323 Channel Driver";
00139 static const char config[] = "h323.conf";
00140 static char default_context[AST_MAX_CONTEXT] = "default";
00141 static struct sockaddr_in bindaddr;
00142
00143 #define GLOBAL_CAPABILITY (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_H261)
00144
00145
00146 static int h323_signalling_port = 1720;
00147 static char gatekeeper[100];
00148 static int gatekeeper_disable = 1;
00149 static int gatekeeper_discover = 0;
00150 static int gkroute = 0;
00151
00152 static int userbyalias = 1;
00153 static int acceptAnonymous = 1;
00154 static int tos = 0;
00155 static char secret[50];
00156 static unsigned int unique = 0;
00157
00158 static call_options_t global_options;
00159
00160
00161 struct oh323_pvt {
00162 ast_mutex_t lock;
00163 call_options_t options;
00164 int alreadygone;
00165 int needdestroy;
00166 call_details_t cd;
00167 struct ast_channel *owner;
00168 struct sockaddr_in sa;
00169 struct sockaddr_in redirip;
00170 int nonCodecCapability;
00171 int outgoing;
00172 char exten[AST_MAX_EXTENSION];
00173 char context[AST_MAX_CONTEXT];
00174 char accountcode[256];
00175 char rdnis[80];
00176 int amaflags;
00177 struct ast_rtp *rtp;
00178 struct ast_dsp *vad;
00179 int nativeformats;
00180 int needhangup;
00181 int hangupcause;
00182 int newstate;
00183 int newcontrol;
00184 int newdigit;
00185 int newduration;
00186 int pref_codec;
00187 int peercapability;
00188 int jointcapability;
00189 struct ast_codec_pref peer_prefs;
00190 int dtmf_pt;
00191 int curDTMF;
00192 int DTMFsched;
00193 int update_rtp_info;
00194 int recvonly;
00195 int txDtmfDigit;
00196 int noInbandDtmf;
00197 int connection_established;
00198 int got_progress;
00199 struct oh323_pvt *next;
00200 } *iflist = NULL;
00201
00202 static struct ast_user_list {
00203 ASTOBJ_CONTAINER_COMPONENTS(struct oh323_user);
00204 } userl;
00205
00206 static struct ast_peer_list {
00207 ASTOBJ_CONTAINER_COMPONENTS(struct oh323_peer);
00208 } peerl;
00209
00210 static struct ast_alias_list {
00211 ASTOBJ_CONTAINER_COMPONENTS(struct oh323_alias);
00212 } aliasl;
00213
00214
00215 static struct sched_context *sched;
00216 static struct io_context *io;
00217
00218
00219 AST_MUTEX_DEFINE_STATIC(iflock);
00220
00221
00222
00223 AST_MUTEX_DEFINE_STATIC(monlock);
00224
00225
00226 AST_MUTEX_DEFINE_STATIC(caplock);
00227
00228
00229 AST_MUTEX_DEFINE_STATIC(h323_reload_lock);
00230 static int h323_reloading = 0;
00231
00232
00233
00234 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00235 static int restart_monitor(void);
00236 static int h323_do_reload(void);
00237
00238 static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause);
00239 static int oh323_digit_begin(struct ast_channel *c, char digit);
00240 static int oh323_digit_end(struct ast_channel *c, char digit, unsigned int duration);
00241 static int oh323_call(struct ast_channel *c, char *dest, int timeout);
00242 static int oh323_hangup(struct ast_channel *c);
00243 static int oh323_answer(struct ast_channel *c);
00244 static struct ast_frame *oh323_read(struct ast_channel *c);
00245 static int oh323_write(struct ast_channel *c, struct ast_frame *frame);
00246 static int oh323_indicate(struct ast_channel *c, int condition, const void *data, size_t datalen);
00247 static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00248
00249 static const struct ast_channel_tech oh323_tech = {
00250 .type = "H323",
00251 .description = tdesc,
00252 .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
00253 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
00254 .requester = oh323_request,
00255 .send_digit_begin = oh323_digit_begin,
00256 .send_digit_end = oh323_digit_end,
00257 .call = oh323_call,
00258 .hangup = oh323_hangup,
00259 .answer = oh323_answer,
00260 .read = oh323_read,
00261 .write = oh323_write,
00262 .indicate = oh323_indicate,
00263 .fixup = oh323_fixup,
00264
00265 #if 0
00266 .bridge = ast_rtp_bridge,
00267 #endif
00268 };
00269
00270 static const char* redirectingreason2str(int redirectingreason)
00271 {
00272 switch (redirectingreason) {
00273 case 0:
00274 return "UNKNOWN";
00275 case 1:
00276 return "BUSY";
00277 case 2:
00278 return "NO_REPLY";
00279 case 0xF:
00280 return "UNCONDITIONAL";
00281 default:
00282 return "NOREDIRECT";
00283 }
00284 }
00285
00286 static void oh323_destroy_alias(struct oh323_alias *alias)
00287 {
00288 if (h323debug)
00289 ast_log(LOG_DEBUG, "Destroying alias '%s'\n", alias->name);
00290 free(alias);
00291 }
00292
00293 static void oh323_destroy_user(struct oh323_user *user)
00294 {
00295 if (h323debug)
00296 ast_log(LOG_DEBUG, "Destroying user '%s'\n", user->name);
00297 ast_free_ha(user->ha);
00298 free(user);
00299 }
00300
00301 static void oh323_destroy_peer(struct oh323_peer *peer)
00302 {
00303 if (h323debug)
00304 ast_log(LOG_DEBUG, "Destroying peer '%s'\n", peer->name);
00305 ast_free_ha(peer->ha);
00306 free(peer);
00307 }
00308
00309 static int oh323_simulate_dtmf_end(const void *data)
00310 {
00311 struct oh323_pvt *pvt = (struct oh323_pvt *)data;
00312
00313 if (pvt) {
00314 ast_mutex_lock(&pvt->lock);
00315
00316 while (pvt->owner && ast_channel_trylock(pvt->owner)) {
00317 DEADLOCK_AVOIDANCE(&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
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 .len = pvt->newduration,
00371 .src = "UPDATE_INFO",
00372 };
00373 if (pvt->newdigit == ' ') {
00374 f.subclass = pvt->curDTMF;
00375 if (pvt->DTMFsched >= 0) {
00376 AST_SCHED_DEL(sched, pvt->DTMFsched);
00377 }
00378 } else {
00379 if (pvt->newduration) {
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);
00397 }
00398 pvt->update_rtp_info = -1;
00399 }
00400 }
00401
00402
00403 static void oh323_update_info(struct ast_channel *c)
00404 {
00405 struct oh323_pvt *pvt = c->tech_pvt;
00406
00407 if (pvt) {
00408 ast_mutex_lock(&pvt->lock);
00409 __oh323_update_info(c, pvt);
00410 ast_mutex_unlock(&pvt->lock);
00411 }
00412 }
00413
00414 static void cleanup_call_details(call_details_t *cd)
00415 {
00416 if (cd->call_token) {
00417 free(cd->call_token);
00418 cd->call_token = NULL;
00419 }
00420 if (cd->call_source_aliases) {
00421 free(cd->call_source_aliases);
00422 cd->call_source_aliases = NULL;
00423 }
00424 if (cd->call_dest_alias) {
00425 free(cd->call_dest_alias);
00426 cd->call_dest_alias = NULL;
00427 }
00428 if (cd->call_source_name) {
00429 free(cd->call_source_name);
00430 cd->call_source_name = NULL;
00431 }
00432 if (cd->call_source_e164) {
00433 free(cd->call_source_e164);
00434 cd->call_source_e164 = NULL;
00435 }
00436 if (cd->call_dest_e164) {
00437 free(cd->call_dest_e164);
00438 cd->call_dest_e164 = NULL;
00439 }
00440 if (cd->sourceIp) {
00441 free(cd->sourceIp);
00442 cd->sourceIp = NULL;
00443 }
00444 if (cd->redirect_number) {
00445 free(cd->redirect_number);
00446 cd->redirect_number = NULL;
00447 }
00448 }
00449
00450 static void __oh323_destroy(struct oh323_pvt *pvt)
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
00461 if (pvt->vad) {
00462 ast_dsp_free(pvt->vad);
00463 }
00464 cleanup_call_details(&pvt->cd);
00465
00466
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 }
00494
00495 static void oh323_destroy(struct oh323_pvt *pvt)
00496 {
00497 if (h323debug) {
00498 ast_log(LOG_DEBUG, "Destroying channel %s\n", (pvt->owner ? pvt->owner->name : "<unknown>"));
00499 }
00500 ast_mutex_lock(&iflock);
00501 ast_mutex_lock(&pvt->lock);
00502 __oh323_destroy(pvt);
00503 ast_mutex_unlock(&iflock);
00504 }
00505
00506 static int oh323_digit_begin(struct ast_channel *c, char digit)
00507 {
00508 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00509 char *token;
00510
00511 if (!pvt) {
00512 ast_log(LOG_ERROR, "No private structure?! This is bad\n");
00513 return -1;
00514 }
00515 ast_mutex_lock(&pvt->lock);
00516 if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833) && (pvt->dtmf_pt > 0)) {
00517
00518 if (h323debug) {
00519 ast_log(LOG_DTMF, "Begin sending out-of-band digit %c on %s\n", digit, c->name);
00520 }
00521 ast_rtp_senddigit_begin(pvt->rtp, digit);
00522 ast_mutex_unlock(&pvt->lock);
00523 } else if (pvt->txDtmfDigit != digit) {
00524
00525 if (h323debug) {
00526 ast_log(LOG_DTMF, "Begin sending inband digit %c on %s\n", digit, c->name);
00527 }
00528 pvt->txDtmfDigit = digit;
00529 token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
00530 ast_mutex_unlock(&pvt->lock);
00531 h323_send_tone(token, digit);
00532 if (token) {
00533 free(token);
00534 }
00535 } else
00536 ast_mutex_unlock(&pvt->lock);
00537 oh323_update_info(c);
00538 return 0;
00539 }
00540
00541
00542
00543
00544
00545 static int oh323_digit_end(struct ast_channel *c, char digit, unsigned int duration)
00546 {
00547 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00548 char *token;
00549
00550 if (!pvt) {
00551 ast_log(LOG_ERROR, "No private structure?! This is bad\n");
00552 return -1;
00553 }
00554 ast_mutex_lock(&pvt->lock);
00555 if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833) && (pvt->dtmf_pt > 0)) {
00556
00557 if (h323debug) {
00558 ast_log(LOG_DTMF, "End sending out-of-band digit %c on %s, duration %d\n", digit, c->name, duration);
00559 }
00560 ast_rtp_senddigit_end(pvt->rtp, digit);
00561 ast_mutex_unlock(&pvt->lock);
00562 } else {
00563
00564 if (h323debug) {
00565 ast_log(LOG_DTMF, "End sending inband digit %c on %s, duration %d\n", digit, c->name, duration);
00566 }
00567 pvt->txDtmfDigit = ' ';
00568 token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
00569 ast_mutex_unlock(&pvt->lock);
00570 h323_send_tone(token, ' ');
00571 if (token) {
00572 free(token);
00573 }
00574 }
00575 oh323_update_info(c);
00576 return 0;
00577 }
00578
00579
00580
00581
00582
00583
00584 static int oh323_call(struct ast_channel *c, char *dest, int timeout)
00585 {
00586 int res = 0;
00587 struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;
00588 const char *addr;
00589 char called_addr[1024];
00590
00591 if (h323debug) {
00592 ast_log(LOG_DEBUG, "Calling to %s on %s\n", dest, c->name);
00593 }
00594 if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
00595 ast_log(LOG_WARNING, "Line is already in use (%s)\n", c->name);
00596 return -1;
00597 }
00598 ast_mutex_lock(&pvt->lock);
00599 if (!gatekeeper_disable) {
00600 if (ast_strlen_zero(pvt->exten)) {
00601 ast_copy_string(called_addr, dest, sizeof(called_addr));
00602 } else {
00603 snprintf(called_addr, sizeof(called_addr), "%s@%s", pvt->exten, dest);
00604 }
00605 } else {
00606 res = htons(pvt->sa.sin_port);
00607 addr = ast_inet_ntoa(pvt->sa.sin_addr);
00608 if (ast_strlen_zero(pvt->exten)) {
00609 snprintf(called_addr, sizeof(called_addr), "%s:%d", addr, res);
00610 } else {
00611 snprintf(called_addr, sizeof(called_addr), "%s@%s:%d", pvt->exten, addr, res);
00612 }
00613 }
00614
00615 called_addr[sizeof(called_addr) - 1] = '\0';
00616
00617 if (c->cid.cid_num)
00618 ast_copy_string(pvt->options.cid_num, c->cid.cid_num, sizeof(pvt->options.cid_num));
00619
00620 if (c->cid.cid_name)
00621 ast_copy_string(pvt->options.cid_name, c->cid.cid_name, sizeof(pvt->options.cid_name));
00622
00623 if (c->cid.cid_rdnis) {
00624 ast_copy_string(pvt->options.cid_rdnis, c->cid.cid_rdnis, sizeof(pvt->options.cid_rdnis));
00625 }
00626
00627 pvt->options.presentation = c->cid.cid_pres;
00628 pvt->options.type_of_number = c->cid.cid_ton;
00629
00630 if ((addr = pbx_builtin_getvar_helper(c, "PRIREDIRECTREASON"))) {
00631 if (!strcasecmp(addr, "UNKNOWN"))
00632 pvt->options.redirect_reason = 0;
00633 else if (!strcasecmp(addr, "BUSY"))
00634 pvt->options.redirect_reason = 1;
00635 else if (!strcasecmp(addr, "NO_REPLY"))
00636 pvt->options.redirect_reason = 2;
00637 else if (!strcasecmp(addr, "UNCONDITIONAL"))
00638 pvt->options.redirect_reason = 15;
00639 else
00640 pvt->options.redirect_reason = -1;
00641 } else
00642 pvt->options.redirect_reason = -1;
00643
00644 pvt->options.transfer_capability = c->transfercapability;
00645
00646
00647 pvt->outgoing = 1;
00648
00649 if (option_verbose > 2)
00650 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", c->transfercapability, ast_transfercapability2str(c->transfercapability));
00651 if (h323debug)
00652 ast_log(LOG_DEBUG, "Placing outgoing call to %s, %d\n", called_addr, pvt->options.dtmfcodec);
00653 ast_mutex_unlock(&pvt->lock);
00654 res = h323_make_call(called_addr, &(pvt->cd), &pvt->options);
00655 if (res) {
00656 ast_log(LOG_NOTICE, "h323_make_call failed(%s)\n", c->name);
00657 return -1;
00658 }
00659 oh323_update_info(c);
00660 return 0;
00661 }
00662
00663 static int oh323_answer(struct ast_channel *c)
00664 {
00665 int res;
00666 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00667 char *token;
00668
00669 if (h323debug)
00670 ast_log(LOG_DEBUG, "Answering on %s\n", c->name);
00671
00672 ast_mutex_lock(&pvt->lock);
00673 token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
00674 ast_mutex_unlock(&pvt->lock);
00675 res = h323_answering_call(token, 0);
00676 if (token)
00677 free(token);
00678
00679 oh323_update_info(c);
00680 if (c->_state != AST_STATE_UP) {
00681 ast_setstate(c, AST_STATE_UP);
00682 }
00683 return res;
00684 }
00685
00686 static int oh323_hangup(struct ast_channel *c)
00687 {
00688 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00689 int q931cause = AST_CAUSE_NORMAL_CLEARING;
00690 char *call_token;
00691
00692
00693 if (h323debug)
00694 ast_log(LOG_DEBUG, "Hanging up and scheduling destroy of call %s\n", c->name);
00695
00696 if (!c->tech_pvt) {
00697 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
00698 return 0;
00699 }
00700 ast_mutex_lock(&pvt->lock);
00701
00702 if (pvt->owner != c) {
00703 ast_log(LOG_WARNING, "Huh? We aren't the owner?\n");
00704 ast_mutex_unlock(&pvt->lock);
00705 return 0;
00706 }
00707
00708 pvt->owner = NULL;
00709 c->tech_pvt = NULL;
00710
00711 if (c->hangupcause) {
00712 q931cause = c->hangupcause;
00713 } else {
00714 const char *cause = pbx_builtin_getvar_helper(c, "DIALSTATUS");
00715 if (cause) {
00716 if (!strcmp(cause, "CONGESTION")) {
00717 q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
00718 } else if (!strcmp(cause, "BUSY")) {
00719 q931cause = AST_CAUSE_USER_BUSY;
00720 } else if (!strcmp(cause, "CHANISUNVAIL")) {
00721 q931cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
00722 } else if (!strcmp(cause, "NOANSWER")) {
00723 q931cause = AST_CAUSE_NO_ANSWER;
00724 } else if (!strcmp(cause, "CANCEL")) {
00725 q931cause = AST_CAUSE_CALL_REJECTED;
00726 }
00727 }
00728 }
00729
00730
00731 if (!pvt->alreadygone && !pvt->hangupcause) {
00732 call_token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
00733 if (call_token) {
00734
00735 ast_mutex_unlock(&pvt->lock);
00736 if (h323_clear_call(call_token, q931cause)) {
00737 ast_log(LOG_WARNING, "ClearCall failed.\n");
00738 }
00739 free(call_token);
00740 ast_mutex_lock(&pvt->lock);
00741 }
00742 }
00743 pvt->needdestroy = 1;
00744 ast_mutex_unlock(&pvt->lock);
00745
00746
00747 ast_module_unref(ast_module_info->self);
00748
00749 return 0;
00750 }
00751
00752 static struct ast_frame *oh323_rtp_read(struct oh323_pvt *pvt)
00753 {
00754
00755 struct ast_frame *f;
00756
00757
00758 if (pvt->options.nat) {
00759 ast_rtp_setnat(pvt->rtp, pvt->options.nat);
00760 pvt->options.nat = 0;
00761 }
00762
00763 f = ast_rtp_read(pvt->rtp);
00764
00765 if (f && (f->frametype == AST_FRAME_DTMF) && !(pvt->options.dtmfmode & H323_DTMF_RFC2833)) {
00766 return &ast_null_frame;
00767 }
00768 if (pvt->owner) {
00769
00770 if (f->frametype == AST_FRAME_VOICE) {
00771 if (f->subclass != pvt->owner->nativeformats) {
00772
00773 if (ast_channel_trylock(pvt->owner)) {
00774 ast_log(LOG_NOTICE, "Format changed but channel is locked. Ignoring frame...\n");
00775 return &ast_null_frame;
00776 }
00777 if (h323debug)
00778 ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
00779 pvt->owner->nativeformats = f->subclass;
00780 pvt->nativeformats = f->subclass;
00781 ast_set_read_format(pvt->owner, pvt->owner->readformat);
00782 ast_set_write_format(pvt->owner, pvt->owner->writeformat);
00783 ast_channel_unlock(pvt->owner);
00784 }
00785
00786 if ((pvt->options.dtmfmode & H323_DTMF_INBAND) && pvt->vad) {
00787 if ((pvt->nativeformats & (AST_FORMAT_SLINEAR | AST_FORMAT_ALAW | AST_FORMAT_ULAW))) {
00788 if (!ast_channel_trylock(pvt->owner)) {
00789 f = ast_dsp_process(pvt->owner, pvt->vad, f);
00790 ast_channel_unlock(pvt->owner);
00791 }
00792 else
00793 ast_log(LOG_NOTICE, "Unable to process inband DTMF while channel is locked\n");
00794 } else if (pvt->nativeformats && !pvt->noInbandDtmf) {
00795 ast_log(LOG_NOTICE, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(f->subclass));
00796 pvt->noInbandDtmf = 1;
00797 }
00798 if (f &&(f->frametype == AST_FRAME_DTMF)) {
00799 if (h323debug)
00800 ast_log(LOG_DTMF, "Received in-band digit %c.\n", f->subclass);
00801 }
00802 }
00803 }
00804 }
00805 return f;
00806 }
00807
00808 static struct ast_frame *oh323_read(struct ast_channel *c)
00809 {
00810 struct ast_frame *fr;
00811 struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;
00812 ast_mutex_lock(&pvt->lock);
00813 __oh323_update_info(c, pvt);
00814 switch(c->fdno) {
00815 case 0:
00816 fr = oh323_rtp_read(pvt);
00817 break;
00818 case 1:
00819 if (pvt->rtp)
00820 fr = ast_rtcp_read(pvt->rtp);
00821 else
00822 fr = &ast_null_frame;
00823 break;
00824 default:
00825 ast_log(LOG_ERROR, "Unable to handle fd %d on channel %s\n", c->fdno, c->name);
00826 fr = &ast_null_frame;
00827 break;
00828 }
00829 ast_mutex_unlock(&pvt->lock);
00830 return fr;
00831 }
00832
00833 static int oh323_write(struct ast_channel *c, struct ast_frame *frame)
00834 {
00835 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00836 int res = 0;
00837 if (frame->frametype != AST_FRAME_VOICE) {
00838 if (frame->frametype == AST_FRAME_IMAGE) {
00839 return 0;
00840 } else {
00841 ast_log(LOG_WARNING, "Can't send %d type frames with H323 write\n", frame->frametype);
00842 return 0;
00843 }
00844 } else {
00845 if (!(frame->subclass & c->nativeformats)) {
00846 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
00847 frame->subclass, c->nativeformats, c->readformat, c->writeformat);
00848 return 0;
00849 }
00850 }
00851 if (pvt) {
00852 ast_mutex_lock(&pvt->lock);
00853 if (pvt->rtp && !pvt->recvonly)
00854 res = ast_rtp_write(pvt->rtp, frame);
00855 __oh323_update_info(c, pvt);
00856 ast_mutex_unlock(&pvt->lock);
00857 }
00858 return res;
00859 }
00860
00861 static int oh323_indicate(struct ast_channel *c, int condition, const void *data, size_t datalen)
00862 {
00863
00864 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00865 char *token = (char *)NULL;
00866 int res = -1;
00867 int got_progress;
00868
00869 ast_mutex_lock(&pvt->lock);
00870 token = (pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL);
00871 got_progress = pvt->got_progress;
00872 if (condition == AST_CONTROL_PROGRESS)
00873 pvt->got_progress = 1;
00874 else if ((condition == AST_CONTROL_BUSY) || (condition == AST_CONTROL_CONGESTION))
00875 pvt->alreadygone = 1;
00876 ast_mutex_unlock(&pvt->lock);
00877
00878 if (h323debug)
00879 ast_log(LOG_DEBUG, "OH323: Indicating %d on %s\n", condition, token);
00880
00881 switch(condition) {
00882 case AST_CONTROL_RINGING:
00883 if (c->_state == AST_STATE_RING || c->_state == AST_STATE_RINGING) {
00884 h323_send_alerting(token);
00885 res = (got_progress ? 0 : -1);
00886 }
00887 break;
00888 case AST_CONTROL_PROGRESS:
00889 if (c->_state != AST_STATE_UP) {
00890
00891 if (!got_progress)
00892 h323_send_progress(token);
00893 res = 0;
00894 }
00895 break;
00896 case AST_CONTROL_BUSY:
00897 if (c->_state != AST_STATE_UP) {
00898 h323_answering_call(token, 1);
00899 ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
00900 res = 0;
00901 }
00902 break;
00903 case AST_CONTROL_CONGESTION:
00904 if (c->_state != AST_STATE_UP) {
00905 h323_answering_call(token, 1);
00906 ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
00907 res = 0;
00908 }
00909 break;
00910 case AST_CONTROL_HOLD:
00911 ast_moh_start(c, data, NULL);
00912 res = 0;
00913 break;
00914 case AST_CONTROL_UNHOLD:
00915 ast_moh_stop(c);
00916 res = 0;
00917 break;
00918 case AST_CONTROL_SRCUPDATE:
00919 ast_rtp_new_source(pvt->rtp);
00920 res = 0;
00921 break;
00922 case AST_CONTROL_SRCCHANGE:
00923 ast_rtp_change_source(pvt->rtp);
00924 res = 0;
00925 break;
00926 case AST_CONTROL_PROCEEDING:
00927 case -1:
00928 break;
00929 default:
00930 ast_log(LOG_WARNING, "OH323: Don't know how to indicate condition %d on %s\n", condition, token);
00931 break;
00932 }
00933
00934 if (h323debug)
00935 ast_log(LOG_DEBUG, "OH323: Indicated %d on %s, res=%d\n", condition, token, res);
00936 if (token)
00937 free(token);
00938 oh323_update_info(c);
00939
00940 return res;
00941 }
00942
00943 static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
00944 {
00945 struct oh323_pvt *pvt = (struct oh323_pvt *) newchan->tech_pvt;
00946
00947 ast_mutex_lock(&pvt->lock);
00948 if (pvt->owner != oldchan) {
00949 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, pvt->owner);
00950 return -1;
00951 }
00952 pvt->owner = newchan;
00953 ast_mutex_unlock(&pvt->lock);
00954 return 0;
00955 }
00956
00957 static int __oh323_rtp_create(struct oh323_pvt *pvt)
00958 {
00959 struct in_addr our_addr;
00960
00961 if (pvt->rtp)
00962 return 0;
00963
00964 if (ast_find_ourip(&our_addr, bindaddr)) {
00965 ast_mutex_unlock(&pvt->lock);
00966 ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n");
00967 return -1;
00968 }
00969 pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, our_addr);
00970 if (!pvt->rtp) {
00971 ast_mutex_unlock(&pvt->lock);
00972 ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
00973 return -1;
00974 }
00975 if (h323debug)
00976 ast_log(LOG_DEBUG, "Created RTP channel\n");
00977
00978 ast_rtp_settos(pvt->rtp, tos);
00979
00980 if (h323debug)
00981 ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat);
00982 ast_rtp_setnat(pvt->rtp, pvt->options.nat);
00983
00984 if (pvt->dtmf_pt > 0)
00985 ast_rtp_set_rtpmap_type(pvt->rtp, pvt->dtmf_pt, "audio", "telephone-event", 0);
00986
00987 if (pvt->peercapability)
00988 ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
00989
00990 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
00991 ast_jb_configure(pvt->owner, &global_jbconf);
00992 pvt->owner->fds[0] = ast_rtp_fd(pvt->rtp);
00993 pvt->owner->fds[1] = ast_rtcp_fd(pvt->rtp);
00994 ast_queue_frame(pvt->owner, &ast_null_frame);
00995 ast_channel_unlock(pvt->owner);
00996 } else
00997 pvt->update_rtp_info = 1;
00998
00999 return 0;
01000 }
01001
01002
01003 static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const char *host)
01004 {
01005 struct ast_channel *ch;
01006 char *cid_num, *cid_name;
01007 int fmt;
01008
01009 if (!ast_strlen_zero(pvt->options.cid_num))
01010 cid_num = pvt->options.cid_num;
01011 else
01012 cid_num = pvt->cd.call_source_e164;
01013
01014 if (!ast_strlen_zero(pvt->options.cid_name))
01015 cid_name = pvt->options.cid_name;
01016 else
01017 cid_name = pvt->cd.call_source_name;
01018
01019
01020 ast_mutex_unlock(&pvt->lock);
01021 ch = ast_channel_alloc(1, state, cid_num, cid_name, pvt->accountcode, pvt->exten, pvt->context, pvt->amaflags, "H323/%s", host);
01022
01023 ast_module_ref(ast_module_info->self);
01024 ast_mutex_lock(&pvt->lock);
01025 if (ch) {
01026 ch->tech = &oh323_tech;
01027 if (!(fmt = pvt->jointcapability) && !(fmt = pvt->options.capability))
01028 fmt = global_options.capability;
01029 ch->nativeformats = ast_codec_choose(&pvt->options.prefs, fmt, 1);
01030 pvt->nativeformats = ch->nativeformats;
01031 fmt = ast_best_codec(ch->nativeformats);
01032 ch->writeformat = fmt;
01033 ch->rawwriteformat = fmt;
01034 ch->readformat = fmt;
01035 ch->rawreadformat = fmt;
01036 #if 0
01037 ch->fds[0] = ast_rtp_fd(pvt->rtp);
01038 ch->fds[1] = ast_rtcp_fd(pvt->rtp);
01039 #endif
01040 #ifdef VIDEO_SUPPORT
01041 if (pvt->vrtp) {
01042 ch->fds[2] = ast_rtp_fd(pvt->vrtp);
01043 ch->fds[3] = ast_rtcp_fd(pvt->vrtp);
01044 }
01045 #endif
01046 #ifdef T38_SUPPORT
01047 if (pvt->udptl) {
01048 ch->fds[4] = ast_udptl_fd(pvt->udptl);
01049 }
01050 #endif
01051 if (state == AST_STATE_RING) {
01052 ch->rings = 1;
01053 }
01054
01055 if (pvt->options.dtmfmode & H323_DTMF_INBAND) {
01056 pvt->vad = ast_dsp_new();
01057 ast_dsp_set_features(pvt->vad, DSP_FEATURE_DTMF_DETECT);
01058 }
01059
01060 ch->tech_pvt = pvt;
01061
01062 pvt->owner = ch;
01063
01064 ast_copy_string(ch->context, pvt->context, sizeof(ch->context));
01065 ast_copy_string(ch->exten, pvt->exten, sizeof(ch->exten));
01066 ch->priority = 1;
01067 if (!ast_strlen_zero(pvt->accountcode)) {
01068 ast_string_field_set(ch, accountcode, pvt->accountcode);
01069 }
01070 if (pvt->amaflags) {
01071 ch->amaflags = pvt->amaflags;
01072 }
01073
01074
01075
01076 ch->cid.cid_ani = ast_strdup(cid_num);
01077
01078 if (pvt->cd.redirect_reason >= 0) {
01079 ch->cid.cid_rdnis = ast_strdup(pvt->cd.redirect_number);
01080 pbx_builtin_setvar_helper(ch, "PRIREDIRECTREASON", redirectingreason2str(pvt->cd.redirect_reason));
01081 }
01082 ch->cid.cid_pres = pvt->cd.presentation;
01083 ch->cid.cid_ton = pvt->cd.type_of_number;
01084
01085 if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) {
01086 ch->cid.cid_dnid = strdup(pvt->exten);
01087 }
01088 if (pvt->cd.transfer_capability >= 0)
01089 ch->transfercapability = pvt->cd.transfer_capability;
01090 if (state != AST_STATE_DOWN) {
01091 if (ast_pbx_start(ch)) {
01092 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name);
01093 ast_hangup(ch);
01094 ch = NULL;
01095 }
01096 }
01097 } else {
01098 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01099 }
01100 return ch;
01101 }
01102
01103 static struct oh323_pvt *oh323_alloc(int callid)
01104 {
01105 struct oh323_pvt *pvt;
01106
01107 pvt = (struct oh323_pvt *) malloc(sizeof(struct oh323_pvt));
01108 if (!pvt) {
01109 ast_log(LOG_ERROR, "Couldn't allocate private structure. This is bad\n");
01110 return NULL;
01111 }
01112 memset(pvt, 0, sizeof(struct oh323_pvt));
01113 pvt->cd.redirect_reason = -1;
01114 pvt->cd.transfer_capability = -1;
01115
01116 if (!callid) {
01117 if ((pvt->cd).call_token == NULL) {
01118 (pvt->cd).call_token = (char *)malloc(128);
01119 }
01120 if (!pvt->cd.call_token) {
01121 ast_log(LOG_ERROR, "Not enough memory to alocate call token\n");
01122 ast_rtp_destroy(pvt->rtp);
01123 free(pvt);
01124 return NULL;
01125 }
01126 memset((char *)(pvt->cd).call_token, 0, 128);
01127 pvt->cd.call_reference = callid;
01128 }
01129 memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01130 pvt->jointcapability = pvt->options.capability;
01131 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01132 pvt->nonCodecCapability |= AST_RTP_DTMF;
01133 } else {
01134 pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01135 }
01136 ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
01137 pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->update_rtp_info = pvt->DTMFsched = -1;
01138 ast_mutex_init(&pvt->lock);
01139
01140 ast_mutex_lock(&iflock);
01141 pvt->next = iflist;
01142 iflist = pvt;
01143 ast_mutex_unlock(&iflock);
01144 return pvt;
01145 }
01146
01147 static struct oh323_pvt *find_call_locked(int call_reference, const char *token)
01148 {
01149 struct oh323_pvt *pvt;
01150
01151 ast_mutex_lock(&iflock);
01152 pvt = iflist;
01153 while(pvt) {
01154 if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) {
01155
01156 if ((token != NULL) && (pvt->cd.call_token != NULL) && (!strcmp(pvt->cd.call_token, token))) {
01157 ast_mutex_lock(&pvt->lock);
01158 ast_mutex_unlock(&iflock);
01159 return pvt;
01160 } else if (token == NULL) {
01161 ast_log(LOG_WARNING, "Call Token is NULL\n");
01162 ast_mutex_lock(&pvt->lock);
01163 ast_mutex_unlock(&iflock);
01164 return pvt;
01165 }
01166 }
01167 pvt = pvt->next;
01168 }
01169 ast_mutex_unlock(&iflock);
01170 return NULL;
01171 }
01172
01173 static int update_state(struct oh323_pvt *pvt, int state, int signal)
01174 {
01175 if (!pvt)
01176 return 0;
01177 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01178 if (state >= 0)
01179 ast_setstate(pvt->owner, state);
01180 if (signal >= 0)
01181 ast_queue_control(pvt->owner, signal);
01182 ast_channel_unlock(pvt->owner);
01183 return 1;
01184 }
01185 else {
01186 if (state >= 0)
01187 pvt->newstate = state;
01188 if (signal >= 0)
01189 pvt->newcontrol = signal;
01190 return 0;
01191 }
01192 }
01193
01194 static struct oh323_alias *build_alias(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
01195 {
01196 struct oh323_alias *alias;
01197 int found = 0;
01198
01199 alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&aliasl, name, name, 0, 0, strcasecmp);
01200
01201 if (alias)
01202 found++;
01203 else {
01204 if (!(alias = (struct oh323_alias *)calloc(1, sizeof(*alias))))
01205 return NULL;
01206 ASTOBJ_INIT(alias);
01207 }
01208 if (!found && name)
01209 ast_copy_string(alias->name, name, sizeof(alias->name));
01210 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01211 if (!strcasecmp(v->name, "e164")) {
01212 ast_copy_string(alias->e164, v->value, sizeof(alias->e164));
01213 } else if (!strcasecmp(v->name, "prefix")) {
01214 ast_copy_string(alias->prefix, v->value, sizeof(alias->prefix));
01215 } else if (!strcasecmp(v->name, "context")) {
01216 ast_copy_string(alias->context, v->value, sizeof(alias->context));
01217 } else if (!strcasecmp(v->name, "secret")) {
01218 ast_copy_string(alias->secret, v->value, sizeof(alias->secret));
01219 } else {
01220 if (strcasecmp(v->value, "h323")) {
01221 ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->name);
01222 }
01223 }
01224 }
01225 ASTOBJ_UNMARK(alias);
01226 return alias;
01227 }
01228
01229 static struct oh323_alias *realtime_alias(const char *alias)
01230 {
01231 struct ast_variable *var, *tmp;
01232 struct oh323_alias *a;
01233
01234 var = ast_load_realtime("h323", "name", alias, NULL);
01235
01236 if (!var)
01237 return NULL;
01238
01239 for (tmp = var; tmp; tmp = tmp->next) {
01240 if (!strcasecmp(tmp->name, "type") &&
01241 !(!strcasecmp(tmp->value, "alias") || !strcasecmp(tmp->value, "h323"))) {
01242 ast_variables_destroy(var);
01243 return NULL;
01244 }
01245 }
01246
01247 a = build_alias(alias, var, NULL, 1);
01248
01249 ast_variables_destroy(var);
01250
01251 return a;
01252 }
01253
01254 #define DEPRECATED(_v, _new_opt) \
01255 ast_log(LOG_WARNING, "Option %s found at line %d has beed deprecated. Use %s instead.\n", (_v)->name, (_v)->lineno, (_new_opt))
01256
01257 static int update_common_options(struct ast_variable *v, struct call_options *options)
01258 {
01259 int tmp;
01260
01261 if (!strcasecmp(v->name, "allow")) {
01262 ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 1);
01263 } else if (!strcasecmp(v->name, "autoframing")) {
01264 options->autoframing = ast_true(v->value);
01265 } else if (!strcasecmp(v->name, "disallow")) {
01266 ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0);
01267 } else if (!strcasecmp(v->name, "dtmfmode")) {
01268 if (!strcasecmp(v->value, "inband")) {
01269 options->dtmfmode = H323_DTMF_INBAND;
01270 } else if (!strcasecmp(v->value, "rfc2833")) {
01271 options->dtmfmode = H323_DTMF_RFC2833;
01272 } else {
01273 ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
01274 options->dtmfmode = H323_DTMF_RFC2833;
01275 }
01276 } else if (!strcasecmp(v->name, "dtmfcodec")) {
01277 tmp = atoi(v->value);
01278 if (tmp < 96)
01279 ast_log(LOG_WARNING, "Invalid %s value %s at line %d\n", v->name, v->value, v->lineno);
01280 else
01281 options->dtmfcodec = tmp;
01282 } else if (!strcasecmp(v->name, "bridge")) {
01283 options->bridge = ast_true(v->value);
01284 } else if (!strcasecmp(v->name, "nat")) {
01285 options->nat = ast_true(v->value);
01286 } else if (!strcasecmp(v->name, "noFastStart")) {
01287 DEPRECATED(v, "fastStart");
01288 options->fastStart = !ast_true(v->value);
01289 } else if (!strcasecmp(v->name, "fastStart")) {
01290 options->fastStart = ast_true(v->value);
01291 } else if (!strcasecmp(v->name, "noH245Tunneling")) {
01292 DEPRECATED(v, "h245Tunneling");
01293 options->h245Tunneling = !ast_true(v->value);
01294 } else if (!strcasecmp(v->name, "h245Tunneling")) {
01295 options->h245Tunneling = ast_true(v->value);
01296 } else if (!strcasecmp(v->name, "noSilenceSuppression")) {
01297 DEPRECATED(v, "silenceSuppression");
01298 options->silenceSuppression = !ast_true(v->value);
01299 } else if (!strcasecmp(v->name, "silenceSuppression")) {
01300 options->silenceSuppression = ast_true(v->value);
01301 } else if (!strcasecmp(v->name, "progress_setup")) {
01302 tmp = atoi(v->value);
01303 if ((tmp != 0) && (tmp != 1) && (tmp != 3) && (tmp != 8)) {
01304 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
01305 tmp = 0;
01306 }
01307 options->progress_setup = tmp;
01308 } else if (!strcasecmp(v->name, "progress_alert")) {
01309 tmp = atoi(v->value);
01310 if ((tmp != 0) && (tmp != 1) && (tmp != 8)) {
01311 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
01312 tmp = 0;
01313 }
01314 options->progress_alert = tmp;
01315 } else if (!strcasecmp(v->name, "progress_audio")) {
01316 options->progress_audio = ast_true(v->value);
01317 } else if (!strcasecmp(v->name, "callerid")) {
01318 ast_callerid_split(v->value, options->cid_name, sizeof(options->cid_name), options->cid_num, sizeof(options->cid_num));
01319 } else if (!strcasecmp(v->name, "fullname")) {
01320 ast_copy_string(options->cid_name, v->value, sizeof(options->cid_name));
01321 } else if (!strcasecmp(v->name, "cid_number")) {
01322 ast_copy_string(options->cid_num, v->value, sizeof(options->cid_num));
01323 } else if (!strcasecmp(v->name, "tunneling")) {
01324 if (!strcasecmp(v->value, "none"))
01325 options->tunnelOptions = 0;
01326 else if (!strcasecmp(v->value, "cisco"))
01327 options->tunnelOptions |= H323_TUNNEL_CISCO;
01328 else if (!strcasecmp(v->value, "qsig"))
01329 options->tunnelOptions |= H323_TUNNEL_QSIG;
01330 else
01331 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
01332 } else
01333 return 1;
01334
01335 return 0;
01336 }
01337 #undef DEPRECATED
01338
01339 static struct oh323_user *build_user(char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
01340 {
01341 struct oh323_user *user;
01342 struct ast_ha *oldha;
01343 int found = 0;
01344 int format;
01345
01346 user = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&userl, name, name, 0, 0, strcmp);
01347
01348 if (user)
01349 found++;
01350 else {
01351 if (!(user = (struct oh323_user *)calloc(1, sizeof(*user))))
01352 return NULL;
01353 ASTOBJ_INIT(user);
01354 }
01355 oldha = user->ha;
01356 user->ha = (struct ast_ha *)NULL;
01357 memcpy(&user->options, &global_options, sizeof(user->options));
01358
01359 ast_copy_string(user->context, default_context, sizeof(user->context));
01360 if (user && !found)
01361 ast_copy_string(user->name, name, sizeof(user->name));
01362
01363 #if 0
01364 if (user->chanvars) {
01365 ast_variables_destroy(user->chanvars);
01366 user->chanvars = NULL;
01367 }
01368 #endif
01369
01370 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01371 if (!update_common_options(v, &user->options))
01372 continue;
01373 if (!strcasecmp(v->name, "context")) {
01374 ast_copy_string(user->context, v->value, sizeof(user->context));
01375 } else if (!strcasecmp(v->name, "secret")) {
01376 ast_copy_string(user->secret, v->value, sizeof(user->secret));
01377 } else if (!strcasecmp(v->name, "accountcode")) {
01378 ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
01379 } else if (!strcasecmp(v->name, "host")) {
01380 if (!strcasecmp(v->value, "dynamic")) {
01381 ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n");
01382 ASTOBJ_UNREF(user, oh323_destroy_user);
01383 return NULL;
01384 } else if (ast_get_ip(&user->addr, v->value)) {
01385 ASTOBJ_UNREF(user, oh323_destroy_user);
01386 return NULL;
01387 }
01388
01389 user->host = 1;
01390 } else if (!strcasecmp(v->name, "amaflags")) {
01391 format = ast_cdr_amaflags2int(v->value);
01392 if (format < 0) {
01393 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
01394 } else {
01395 user->amaflags = format;
01396 }
01397 } else if (!strcasecmp(v->name, "permit") ||
01398 !strcasecmp(v->name, "deny")) {
01399 user->ha = ast_append_ha(v->name, v->value, user->ha);
01400 }
01401 }
01402 ASTOBJ_UNMARK(user);
01403 ast_free_ha(oldha);
01404 return user;
01405 }
01406
01407 static struct oh323_user *realtime_user(const call_details_t *cd)
01408 {
01409 struct ast_variable *var, *tmp;
01410 struct oh323_user *user;
01411 char *username;
01412
01413 if (userbyalias)
01414 var = ast_load_realtime("h323", "name", username = cd->call_source_aliases, NULL);
01415 else {
01416 username = (char *)NULL;
01417 var = ast_load_realtime("h323", "host", cd->sourceIp, NULL);
01418 }
01419
01420 if (!var)
01421 return NULL;
01422
01423 for (tmp = var; tmp; tmp = tmp->next) {
01424 if (!strcasecmp(tmp->name, "type") &&
01425 !(!strcasecmp(tmp->value, "user") || !strcasecmp(tmp->value, "friend"))) {
01426 ast_variables_destroy(var);
01427 return NULL;
01428 } else if (!username && !strcasecmp(tmp->name, "name"))
01429 username = tmp->value;
01430 }
01431
01432 if (!username) {
01433 ast_log(LOG_WARNING, "Cannot determine user name for IP address %s\n", cd->sourceIp);
01434 ast_variables_destroy(var);
01435 return NULL;
01436 }
01437
01438 user = build_user(username, var, NULL, 1);
01439
01440 ast_variables_destroy(var);
01441
01442 return user;
01443 }
01444
01445 static struct oh323_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
01446 {
01447 struct oh323_peer *peer;
01448 struct ast_ha *oldha;
01449 int found = 0;
01450
01451 peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp);
01452
01453 if (peer)
01454 found++;
01455 else {
01456 if (!(peer = (struct oh323_peer*)calloc(1, sizeof(*peer))))
01457 return NULL;
01458 ASTOBJ_INIT(peer);
01459 }
01460 oldha = peer->ha;
01461 peer->ha = NULL;
01462 memcpy(&peer->options, &global_options, sizeof(peer->options));
01463 peer->addr.sin_port = htons(h323_signalling_port);
01464 peer->addr.sin_family = AF_INET;
01465 if (!found && name)
01466 ast_copy_string(peer->name, name, sizeof(peer->name));
01467
01468 #if 0
01469 if (peer->chanvars) {
01470 ast_variables_destroy(peer->chanvars);
01471 peer->chanvars = NULL;
01472 }
01473 #endif
01474
01475 peer->mailbox[0] = '\0';
01476
01477 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01478 if (!update_common_options(v, &peer->options))
01479 continue;
01480 if (!strcasecmp(v->name, "host")) {
01481 if (!strcasecmp(v->value, "dynamic")) {
01482 ast_log(LOG_ERROR, "Dynamic host configuration not implemented.\n");
01483 ASTOBJ_UNREF(peer, oh323_destroy_peer);
01484 return NULL;
01485 }
01486 if (ast_get_ip(&peer->addr, v->value)) {
01487 ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value);
01488 ASTOBJ_UNREF(peer, oh323_destroy_peer);
01489 return NULL;
01490 }
01491 } else if (!strcasecmp(v->name, "port")) {
01492 peer->addr.sin_port = htons(atoi(v->value));
01493 } else if (!strcasecmp(v->name, "permit") ||
01494 !strcasecmp(v->name, "deny")) {
01495 peer->ha = ast_append_ha(v->name, v->value, peer->ha);
01496 } else if (!strcasecmp(v->name, "mailbox")) {
01497 ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox));
01498 } else if (!strcasecmp(v->name, "hasvoicemail")) {
01499 if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) {
01500 ast_copy_string(peer->mailbox, name, sizeof(peer->mailbox));
01501 }
01502 }
01503 }
01504 ASTOBJ_UNMARK(peer);
01505 ast_free_ha(oldha);
01506 return peer;
01507 }
01508
01509 static struct oh323_peer *realtime_peer(const char *peername, struct sockaddr_in *sin)
01510 {
01511 struct oh323_peer *peer;
01512 struct ast_variable *var;
01513 struct ast_variable *tmp;
01514 const char *addr;
01515
01516
01517 if (peername)
01518 var = ast_load_realtime("h323", "name", peername, addr = NULL);
01519 else if (sin)
01520 var = ast_load_realtime("h323", "host", addr = ast_inet_ntoa(sin->sin_addr), NULL);
01521 else
01522 return NULL;
01523
01524 if (!var)
01525 return NULL;
01526
01527 for (tmp = var; tmp; tmp = tmp->next) {
01528
01529 if (!strcasecmp(tmp->name, "type") &&
01530 !(!strcasecmp(tmp->value, "peer") || !strcasecmp(tmp->value, "friend"))) {
01531 ast_variables_destroy(var);
01532 return NULL;
01533 } else if (!peername && !strcasecmp(tmp->name, "name")) {
01534 peername = tmp->value;
01535 }
01536 }
01537
01538 if (!peername) {
01539 ast_log(LOG_WARNING, "Cannot determine peer name for IP address %s\n", addr);
01540 ast_variables_destroy(var);
01541 return NULL;
01542 }
01543
01544
01545 peer = build_peer(peername, var, NULL, 1);
01546
01547 ast_variables_destroy(var);
01548
01549 return peer;
01550 }
01551
01552 static int oh323_addrcmp_str(struct in_addr inaddr, char *addr)
01553 {
01554 return strcmp(ast_inet_ntoa(inaddr), addr);
01555 }
01556
01557 static struct oh323_user *find_user(const call_details_t *cd, int realtime)
01558 {
01559 struct oh323_user *u;
01560
01561 if (userbyalias)
01562 u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases);
01563 else
01564 u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str);
01565
01566 if (!u && realtime)
01567 u = realtime_user(cd);
01568
01569 if (!u && h323debug)
01570 ast_log(LOG_DEBUG, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp);
01571
01572 return u;
01573 }
01574
01575 static int oh323_addrcmp(struct sockaddr_in addr, struct sockaddr_in *sin)
01576 {
01577 int res;
01578
01579 if (!sin)
01580 res = -1;
01581 else
01582 res = inaddrcmp(&addr , sin);
01583
01584 return res;
01585 }
01586
01587 static struct oh323_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime)
01588 {
01589 struct oh323_peer *p;
01590
01591 if (peer)
01592 p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
01593 else
01594 p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
01595
01596 if (!p && realtime)
01597 p = realtime_peer(peer, sin);
01598
01599 if (!p && h323debug)
01600 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>"));
01601
01602 return p;
01603 }
01604
01605 static int create_addr(struct oh323_pvt *pvt, char *opeer)
01606 {
01607 struct hostent *hp;
01608 struct ast_hostent ahp;
01609 struct oh323_peer *p;
01610 int portno;
01611 int found = 0;
01612 char *port;
01613 char *hostn;
01614 char peer[256] = "";
01615
01616 ast_copy_string(peer, opeer, sizeof(peer));
01617 port = strchr(peer, ':');
01618 if (port) {
01619 *port = '\0';
01620 port++;
01621 }
01622 pvt->sa.sin_family = AF_INET;
01623 p = find_peer(peer, NULL, 1);
01624 if (p) {
01625 found++;
01626 memcpy(&pvt->options, &p->options, sizeof(pvt->options));
01627 pvt->jointcapability = pvt->options.capability;
01628 if (pvt->options.dtmfmode) {
01629 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01630 pvt->nonCodecCapability |= AST_RTP_DTMF;
01631 } else {
01632 pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01633 }
01634 }
01635 if (p->addr.sin_addr.s_addr) {
01636 pvt->sa.sin_addr = p->addr.sin_addr;
01637 pvt->sa.sin_port = p->addr.sin_port;
01638 }
01639 ASTOBJ_UNREF(p, oh323_destroy_peer);
01640 }
01641 if (!p && !found) {
01642 hostn = peer;
01643 if (port) {
01644 portno = atoi(port);
01645 } else {
01646 portno = h323_signalling_port;
01647 }
01648 hp = ast_gethostbyname(hostn, &ahp);
01649 if (hp) {
01650 memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
01651 pvt->sa.sin_port = htons(portno);
01652
01653 p = find_peer(NULL, &pvt->sa, 1);
01654 memcpy(&pvt->options, (p ? &p->options : &global_options), sizeof(pvt->options));
01655 pvt->jointcapability = pvt->options.capability;
01656 if (p) {
01657 ASTOBJ_UNREF(p, oh323_destroy_peer);
01658 }
01659 if (pvt->options.dtmfmode) {
01660 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01661 pvt->nonCodecCapability |= AST_RTP_DTMF;
01662 } else {
01663 pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01664 }
01665 }
01666 return 0;
01667 } else {
01668 ast_log(LOG_WARNING, "No such host: %s\n", peer);
01669 return -1;
01670 }
01671 } else if (!found) {
01672 return -1;
01673 } else {
01674 return 0;
01675 }
01676 }
01677 static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause)
01678 {
01679 int oldformat;
01680 struct oh323_pvt *pvt;
01681 struct ast_channel *tmpc = NULL;
01682 char *dest = (char *)data;
01683 char *ext, *host;
01684 char *h323id = NULL;
01685 char tmp[256], tmp1[256];
01686
01687 if (h323debug)
01688 ast_log(LOG_DEBUG, "type=%s, format=%d, data=%s.\n", type, format, (char *)data);
01689
01690 pvt = oh323_alloc(0);
01691 if (!pvt) {
01692 ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data);
01693 return NULL;
01694 }
01695 oldformat = format;
01696 format &= ((AST_FORMAT_MAX_AUDIO << 1) - 1);
01697 if (!format) {
01698 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
01699 oh323_destroy(pvt);
01700 if (cause)
01701 *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
01702 return NULL;
01703 }
01704 ast_copy_string(tmp, dest, sizeof(tmp));
01705 host = strchr(tmp, '@');
01706 if (host) {
01707 *host = '\0';
01708 host++;
01709 ext = tmp;
01710 } else {
01711 ext = strrchr(tmp, '/');
01712 if (ext)
01713 *ext++ = '\0';
01714 host = tmp;
01715 }
01716 strtok_r(host, "/", &(h323id));
01717 if (!ast_strlen_zero(h323id)) {
01718 h323_set_id(h323id);
01719 }
01720 if (ext) {
01721 ast_copy_string(pvt->exten, ext, sizeof(pvt->exten));
01722 }
01723 if (h323debug)
01724 ast_log(LOG_DEBUG, "Extension: %s Host: %s\n", pvt->exten, host);
01725
01726 if (gatekeeper_disable) {
01727 if (create_addr(pvt, host)) {
01728 oh323_destroy(pvt);
01729 if (cause)
01730 *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01731 return NULL;
01732 }
01733 }
01734 else {
01735 memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01736 pvt->jointcapability = pvt->options.capability;
01737 if (pvt->options.dtmfmode) {
01738 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01739 pvt->nonCodecCapability |= AST_RTP_DTMF;
01740 } else {
01741 pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01742 }
01743 }
01744 }
01745
01746 ast_mutex_lock(&caplock);
01747
01748 snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
01749 tmp1[sizeof(tmp1)-1] = '\0';
01750 ast_mutex_unlock(&caplock);
01751
01752 ast_mutex_lock(&pvt->lock);
01753 tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1);
01754 ast_mutex_unlock(&pvt->lock);
01755 if (!tmpc) {
01756 oh323_destroy(pvt);
01757 if (cause)
01758 *cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
01759 }
01760 ast_update_use_count();
01761 restart_monitor();
01762 return tmpc;
01763 }
01764
01765
01766 static struct oh323_alias *find_alias(const char *source_aliases, int realtime)
01767 {
01768 struct oh323_alias *a;
01769
01770 a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
01771
01772 if (!a && realtime)
01773 a = realtime_alias(source_aliases);
01774
01775 return a;
01776 }
01777
01778
01779
01780
01781
01782 static int receive_digit(unsigned call_reference, char digit, const char *token, int duration)
01783 {
01784 struct oh323_pvt *pvt;
01785 int res;
01786
01787 pvt = find_call_locked(call_reference, token);
01788 if (!pvt) {
01789 ast_log(LOG_ERROR, "Received digit '%c' (%u ms) for call %s without private structure\n", digit, duration, token);
01790 return -1;
01791 }
01792 if (h323debug)
01793 ast_log(LOG_DTMF, "Received %s digit '%c' (%u ms) for call %s\n", (digit == ' ' ? "update for" : "new"), (digit == ' ' ? pvt->curDTMF : digit), duration, token);
01794
01795 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01796 if (digit == '!')
01797 res = ast_queue_control(pvt->owner, AST_CONTROL_FLASH);
01798 else {
01799 struct ast_frame f = {
01800 .frametype = AST_FRAME_DTMF_END,
01801 .subclass = digit,
01802 .samples = duration * 8,
01803 .len = duration,
01804 .src = "SEND_DIGIT",
01805 };
01806 if (digit == ' ') {
01807 f.subclass = pvt->curDTMF;
01808 AST_SCHED_DEL(sched, pvt->DTMFsched);
01809 } else {
01810 if (pvt->DTMFsched >= 0) {
01811
01812 AST_SCHED_DEL(sched, pvt->DTMFsched);
01813 f.subclass = pvt->curDTMF;
01814 f.samples = f.len = 0;
01815 ast_queue_frame(pvt->owner, &f);
01816
01817 f.subclass = digit;
01818 f.samples = duration * 8;
01819 f.len = duration;
01820 }
01821 if (duration) {
01822 f.frametype = AST_FRAME_DTMF_BEGIN;
01823 pvt->DTMFsched = ast_sched_add(sched, duration, oh323_simulate_dtmf_end, pvt);
01824 if (h323debug)
01825 ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", duration, pvt->DTMFsched);
01826 }
01827 pvt->curDTMF = digit;
01828 }
01829 res = ast_queue_frame(pvt->owner, &f);
01830 }
01831 ast_channel_unlock(pvt->owner);
01832 } else {
01833 if (digit == '!')
01834 pvt->newcontrol = AST_CONTROL_FLASH;
01835 else {
01836 pvt->newduration = duration;
01837 pvt->newdigit = digit;
01838 }
01839 res = 0;
01840 }
01841 ast_mutex_unlock(&pvt->lock);
01842 return res;
01843 }
01844
01845
01846
01847
01848
01849
01850 static struct rtp_info *external_rtp_create(unsigned call_reference, const char * token)
01851 {
01852 struct oh323_pvt *pvt;
01853 struct sockaddr_in us;
01854 struct rtp_info *info;
01855
01856 info = (struct rtp_info *)malloc(sizeof(struct rtp_info));
01857 if (!info) {
01858 ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
01859 return NULL;
01860 }
01861 pvt = find_call_locked(call_reference, token);
01862 if (!pvt) {
01863 free(info);
01864 ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
01865 return NULL;
01866 }
01867 if (!pvt->rtp)
01868 __oh323_rtp_create(pvt);
01869 if (!pvt->rtp) {
01870 ast_mutex_unlock(&pvt->lock);
01871 free(info);
01872 ast_log(LOG_ERROR, "No RTP stream is available for call %s (%d)", token, call_reference);
01873 return NULL;
01874 }
01875
01876 ast_rtp_get_us(pvt->rtp, &us);
01877 ast_mutex_unlock(&pvt->lock);
01878
01879 ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
01880 info->port = ntohs(us.sin_port);
01881 if (h323debug)
01882 ast_log(LOG_DEBUG, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
01883 return info;
01884 }
01885
01886
01887
01888
01889 struct rtpPayloadType {
01890 int isAstFormat;
01891 int code;
01892 };
01893
01894
01895
01896
01897
01898
01899 static void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt)
01900 {
01901 struct oh323_pvt *pvt;
01902 struct sockaddr_in them;
01903 struct rtpPayloadType rtptype;
01904 int nativeformats_changed;
01905 enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE;
01906
01907 if (h323debug)
01908 ast_log(LOG_DEBUG, "Setting up RTP connection for %s\n", token);
01909
01910
01911 pvt = find_call_locked(call_reference, token);
01912 if (!pvt) {
01913 ast_log(LOG_ERROR, "Something is wrong: rtp\n");
01914 return;
01915 }
01916 if (pvt->alreadygone) {
01917 ast_mutex_unlock(&pvt->lock);
01918 return;
01919 }
01920
01921 if (!pvt->rtp)
01922 __oh323_rtp_create(pvt);
01923
01924 them.sin_family = AF_INET;
01925
01926 them.sin_addr.s_addr = inet_addr(remoteIp);
01927 them.sin_port = htons(remotePort);
01928
01929 if (them.sin_addr.s_addr) {
01930 ast_rtp_set_peer(pvt->rtp, &them);
01931 if (pvt->recvonly) {
01932 pvt->recvonly = 0;
01933 rtp_change = NEED_UNHOLD;
01934 }
01935 } else {
01936 ast_rtp_stop(pvt->rtp);
01937 if (!pvt->recvonly) {
01938 pvt->recvonly = 1;
01939 rtp_change = NEED_HOLD;
01940 }
01941 }
01942
01943
01944 nativeformats_changed = 0;
01945 if (pt != 128 && pvt->rtp) {
01946 rtptype = ast_rtp_lookup_pt(pvt->rtp, pt);
01947 if (h323debug)
01948 ast_log(LOG_DEBUG, "Native format is set to %d from %d by RTP payload type %d\n", rtptype.code, pvt->nativeformats, pt);
01949 if (pvt->nativeformats != rtptype.code) {
01950 pvt->nativeformats = rtptype.code;
01951 nativeformats_changed = 1;
01952 }
01953 } else if (h323debug)
01954 ast_log(LOG_NOTICE, "Payload type is unknown, formats isn't changed\n");
01955
01956
01957 if (nativeformats_changed || pvt->options.progress_audio || (rtp_change != NEED_NONE)) {
01958 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01959
01960 if (pvt->owner->nativeformats != pvt->nativeformats) {
01961 if (h323debug)
01962 ast_log(LOG_DEBUG, "Native format changed to %d from %d, read format is %d, write format is %d\n", pvt->nativeformats, pvt->owner->nativeformats, pvt->owner->readformat, pvt->owner->writeformat);
01963 pvt->owner->nativeformats = pvt->nativeformats;
01964 ast_set_read_format(pvt->owner, pvt->owner->readformat);
01965 ast_set_write_format(pvt->owner, pvt->owner->writeformat);
01966 }
01967 if (pvt->options.progress_audio)
01968 ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);
01969 switch (rtp_change) {
01970 case NEED_HOLD:
01971 ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
01972 break;
01973 case NEED_UNHOLD:
01974 ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
01975 break;
01976 default:
01977 break;
01978 }
01979 ast_channel_unlock(pvt->owner);
01980 }
01981 else {
01982 if (pvt->options.progress_audio)
01983 pvt->newcontrol = AST_CONTROL_PROGRESS;
01984 else if (rtp_change == NEED_HOLD)
01985 pvt->newcontrol = AST_CONTROL_HOLD;
01986 else if (rtp_change == NEED_UNHOLD)
01987 pvt->newcontrol = AST_CONTROL_UNHOLD;
01988 if (h323debug)
01989 ast_log(LOG_DEBUG, "RTP connection preparation for %s is pending...\n", token);
01990 }
01991 }
01992 ast_mutex_unlock(&pvt->lock);
01993
01994 if (h323debug)
01995 ast_log(LOG_DEBUG, "RTP connection prepared for %s\n", token);
01996
01997 return;
01998 }
01999
02000
02001
02002
02003
02004 static void connection_made(unsigned call_reference, const char *token)
02005 {
02006 struct oh323_pvt *pvt;
02007
02008 if (h323debug)
02009 ast_log(LOG_DEBUG, "Call %s answered\n", token);
02010
02011 pvt = find_call_locked(call_reference, token);
02012 if (!pvt) {
02013 ast_log(LOG_ERROR, "Something is wrong: connection\n");
02014 return;
02015 }
02016
02017
02018 if (!pvt->outgoing) {
02019 ast_mutex_unlock(&pvt->lock);
02020 return;
02021 }
02022
02023 if (!pvt->connection_established) {
02024 pvt->connection_established = 1;
02025 update_state(pvt, -1, AST_CONTROL_ANSWER);
02026 }
02027 ast_mutex_unlock(&pvt->lock);
02028 return;
02029 }
02030
02031 static int progress(unsigned call_reference, const char *token, int inband)
02032 {
02033 struct oh323_pvt *pvt;
02034
02035 if (h323debug)
02036 ast_log(LOG_DEBUG, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
02037
02038 pvt = find_call_locked(call_reference, token);
02039 if (!pvt) {
02040 ast_log(LOG_ERROR, "Private structure not found in progress.\n");
02041 return -1;
02042 }
02043 if (!pvt->owner) {
02044 ast_mutex_unlock(&pvt->lock);
02045 ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");
02046 return -1;
02047 }
02048 update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));
02049 ast_mutex_unlock(&pvt->lock);
02050
02051 return 0;
02052 }
02053
02054
02055
02056
02057
02058
02059 static call_options_t *setup_incoming_call(call_details_t *cd)
02060 {
02061 struct oh323_pvt *pvt;
02062 struct oh323_user *user = NULL;
02063 struct oh323_alias *alias = NULL;
02064
02065 if (h323debug)
02066 ast_log(LOG_DEBUG, "Setting up incoming call for %s\n", cd->call_token);
02067
02068
02069 pvt = oh323_alloc(cd->call_reference);
02070
02071 if (!pvt) {
02072 ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
02073 cleanup_call_details(cd);
02074 return NULL;
02075 }
02076
02077
02078 memcpy(&pvt->cd, cd, sizeof(pvt->cd));
02079 memcpy(&pvt->options, &global_options, sizeof(pvt->options));
02080 pvt->jointcapability = pvt->options.capability;
02081
02082 if (h323debug) {
02083 ast_verbose(VERBOSE_PREFIX_3 "Setting up Call\n");
02084 ast_verbose(VERBOSE_PREFIX_3 " \tCall token: [%s]\n", pvt->cd.call_token);
02085 ast_verbose(VERBOSE_PREFIX_3 " \tCalling party name: [%s]\n", pvt->cd.call_source_name);
02086 ast_verbose(VERBOSE_PREFIX_3 " \tCalling party number: [%s]\n", pvt->cd.call_source_e164);
02087 ast_verbose(VERBOSE_PREFIX_3 " \tCalled party name: [%s]\n", pvt->cd.call_dest_alias);
02088 ast_verbose(VERBOSE_PREFIX_3 " \tCalled party number: [%s]\n", pvt->cd.call_dest_e164);
02089 if (pvt->cd.redirect_reason >= 0)
02090 ast_verbose(VERBOSE_PREFIX_3 " \tRedirecting party number: [%s] (reason %d)\n", pvt->cd.redirect_number, pvt->cd.redirect_reason);
02091 ast_verbose(VERBOSE_PREFIX_3 " \tCalling party IP: [%s]\n", pvt->cd.sourceIp);
02092 }
02093
02094
02095 if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && !gatekeeper_disable) {
02096 if (!ast_strlen_zero(cd->call_dest_e164)) {
02097 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02098 ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02099 } else {
02100 alias = find_alias(cd->call_dest_alias, 1);
02101 if (!alias) {
02102 ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias);
02103 oh323_destroy(pvt);
02104 return NULL;
02105 }
02106 ast_copy_string(pvt->exten, alias->name, sizeof(pvt->exten));
02107 ast_copy_string(pvt->context, alias->context, sizeof(pvt->context));
02108 }
02109 } else {
02110
02111
02112 user = find_user(cd, 1);
02113 if (!user) {
02114 if (!acceptAnonymous) {
02115 ast_log(LOG_NOTICE, "Anonymous call from '%s@%s' rejected\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02116 oh323_destroy(pvt);
02117 return NULL;
02118 }
02119 if (ast_strlen_zero(default_context)) {
02120 ast_log(LOG_ERROR, "Call from '%s@%s' rejected due to no default context\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02121 oh323_destroy(pvt);
02122 return NULL;
02123 }
02124 ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02125 if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02126 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02127 } else {
02128 ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02129 }
02130 if (h323debug)
02131 ast_log(LOG_DEBUG, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten);
02132 } else {
02133 if (user->host) {
02134 if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) {
02135 if (ast_strlen_zero(user->context)) {
02136 if (ast_strlen_zero(default_context)) {
02137 ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp);
02138 oh323_destroy(pvt);
02139 ASTOBJ_UNREF(user, oh323_destroy_user);
02140 return NULL;
02141 }
02142 ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02143 } else {
02144 ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02145 }
02146 pvt->exten[0] = 'i';
02147 pvt->exten[1] = '\0';
02148 ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp);
02149 oh323_destroy(pvt);
02150 ASTOBJ_UNREF(user, oh323_destroy_user);
02151 return NULL;
02152 }
02153 }
02154 ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02155 memcpy(&pvt->options, &user->options, sizeof(pvt->options));
02156 pvt->jointcapability = pvt->options.capability;
02157 if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02158 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02159 } else {
02160 ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02161 }
02162 if (!ast_strlen_zero(user->accountcode)) {
02163 ast_copy_string(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode));
02164 }
02165 if (user->amaflags) {
02166 pvt->amaflags = user->amaflags;
02167 }
02168 ASTOBJ_UNREF(user, oh323_destroy_user);
02169 }
02170 }
02171 return &pvt->options;
02172 }
02173
02174
02175
02176
02177
02178
02179 static int answer_call(unsigned call_reference, const char *token)
02180 {
02181 struct oh323_pvt *pvt;
02182 struct ast_channel *c = NULL;
02183 enum {ext_original, ext_s, ext_i, ext_notexists} try_exten;
02184 char tmp_exten[sizeof(pvt->exten)];
02185
02186 if (h323debug)
02187 ast_log(LOG_DEBUG, "Preparing Asterisk to answer for %s\n", token);
02188
02189
02190 pvt = find_call_locked(call_reference, token);
02191 if (!pvt) {
02192 ast_log(LOG_ERROR, "Something is wrong: answer_call\n");
02193 return 0;
02194 }
02195
02196 ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten));
02197
02198
02199 if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) {
02200 if (tmp_exten[0] == 's')
02201 try_exten = ext_s;
02202 else if (tmp_exten[0] == 'i')
02203 try_exten = ext_i;
02204 else
02205 try_exten = ext_original;
02206 } else
02207 try_exten = ext_original;
02208 do {
02209 if (ast_exists_extension(NULL, pvt->context, tmp_exten, 1, NULL))
02210 break;
02211 switch (try_exten) {
02212 case ext_original:
02213 tmp_exten[0] = 's';
02214 tmp_exten[1] = '\0';
02215 try_exten = ext_s;
02216 break;
02217 case ext_s:
02218 tmp_exten[0] = 'i';
02219 try_exten = ext_i;
02220 break;
02221 case ext_i:
02222 try_exten = ext_notexists;
02223 break;
02224 default:
02225 break;
02226 }
02227 } while (try_exten != ext_notexists);
02228
02229
02230 if (try_exten == ext_notexists) {
02231 ast_log(LOG_NOTICE, "Dropping call because extensions '%s', 's' and 'i' doesn't exists in context [%s]\n", pvt->exten, pvt->context);
02232 ast_mutex_unlock(&pvt->lock);
02233 h323_clear_call(token, AST_CAUSE_UNALLOCATED);
02234 return 0;
02235 } else if ((try_exten != ext_original) && (strcmp(pvt->exten, tmp_exten) != 0)) {
02236 if (h323debug)
02237 ast_log(LOG_DEBUG, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context);
02238 ast_copy_string(pvt->exten, tmp_exten, sizeof(pvt->exten));
02239 }
02240
02241
02242 c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token);
02243
02244
02245 ast_mutex_unlock(&pvt->lock);
02246 if (!c) {
02247 ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n");
02248 return 0;
02249 }
02250 return 1;
02251 }
02252
02253
02254
02255
02256
02257
02258 static int setup_outgoing_call(call_details_t *cd)
02259 {
02260
02261 cleanup_call_details(cd);
02262
02263 return 1;
02264 }
02265
02266
02267
02268
02269
02270 static void chan_ringing(unsigned call_reference, const char *token)
02271 {
02272 struct oh323_pvt *pvt;
02273
02274 if (h323debug)
02275 ast_log(LOG_DEBUG, "Ringing on %s\n", token);
02276
02277 pvt = find_call_locked(call_reference, token);
02278 if (!pvt) {
02279 ast_log(LOG_ERROR, "Something is wrong: ringing\n");
02280 return;
02281 }
02282 if (!pvt->owner) {
02283 ast_mutex_unlock(&pvt->lock);
02284 ast_log(LOG_ERROR, "Channel has no owner\n");
02285 return;
02286 }
02287 update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING);
02288 ast_mutex_unlock(&pvt->lock);
02289 return;
02290 }
02291
02292
02293
02294
02295
02296 static void cleanup_connection(unsigned call_reference, const char *call_token)
02297 {
02298 struct oh323_pvt *pvt;
02299
02300 if (h323debug)
02301 ast_log(LOG_DEBUG, "Cleaning connection to %s\n", call_token);
02302
02303 while (1) {
02304 pvt = find_call_locked(call_reference, call_token);
02305 if (!pvt) {
02306 if (h323debug)
02307 ast_log(LOG_DEBUG, "No connection for %s\n", call_token);
02308 return;
02309 }
02310 if (!pvt->owner || !ast_channel_trylock(pvt->owner))
02311 break;
02312 #if 1
02313 #ifdef DEBUG_THREADS
02314 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]);
02315 #else
02316 ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token);
02317 #endif
02318 #endif
02319 ast_mutex_unlock(&pvt->lock);
02320 usleep(1);
02321 }
02322 if (pvt->rtp) {
02323
02324 ast_rtp_destroy(pvt->rtp);
02325 pvt->rtp = NULL;
02326 }
02327
02328 if (pvt->vad) {
02329 ast_dsp_free(pvt->vad);
02330 pvt->vad = NULL;
02331 }
02332 cleanup_call_details(&pvt->cd);
02333 pvt->alreadygone = 1;
02334
02335 if (pvt->owner) {
02336 pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02337 ast_queue_hangup(pvt->owner);
02338 ast_channel_unlock(pvt->owner);
02339 }
02340 ast_mutex_unlock(&pvt->lock);
02341 if (h323debug)
02342 ast_log(LOG_DEBUG, "Connection to %s cleaned\n", call_token);
02343 return;
02344 }
02345
02346 static void hangup_connection(unsigned int call_reference, const char *token, int cause)
02347 {
02348 struct oh323_pvt *pvt;
02349
02350 if (h323debug) {
02351 ast_log(LOG_DEBUG, "Hanging up connection to %s with cause %d\n", token, cause);
02352 }
02353
02354 pvt = find_call_locked(call_reference, token);
02355 if (!pvt) {
02356 if (h323debug) {
02357 ast_log(LOG_DEBUG, "Connection to %s already cleared\n", token);
02358 }
02359 return;
02360 }
02361 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02362 pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02363 pvt->owner->hangupcause = pvt->hangupcause = cause;
02364 ast_queue_hangup(pvt->owner);
02365 ast_channel_unlock(pvt->owner);
02366 }
02367 else {
02368 pvt->needhangup = 1;
02369 pvt->hangupcause = cause;
02370 if (h323debug)
02371 ast_log(LOG_DEBUG, "Hangup for %s is pending\n", token);
02372 }
02373 ast_mutex_unlock(&pvt->lock);
02374 }
02375
02376 static void set_dtmf_payload(unsigned call_reference, const char *token, int payload)
02377 {
02378 struct oh323_pvt *pvt;
02379
02380 if (h323debug)
02381 ast_log(LOG_DEBUG, "Setting DTMF payload to %d on %s\n", payload, token);
02382
02383 pvt = find_call_locked(call_reference, token);
02384 if (!pvt) {
02385 return;
02386 }
02387 if (pvt->rtp) {
02388 ast_rtp_set_rtpmap_type(pvt->rtp, payload, "audio", "telephone-event", 0);
02389 }
02390 pvt->dtmf_pt = payload;
02391 ast_mutex_unlock(&pvt->lock);
02392 if (h323debug)
02393 ast_log(LOG_DEBUG, "DTMF payload on %s set to %d\n", token, payload);
02394 }
02395
02396 static void set_peer_capabilities(unsigned call_reference, const char *token, int capabilities, struct ast_codec_pref *prefs)
02397 {
02398 struct oh323_pvt *pvt;
02399
02400 if (h323debug)
02401 ast_log(LOG_DEBUG, "Got remote capabilities from connection %s\n", token);
02402
02403 pvt = find_call_locked(call_reference, token);
02404 if (!pvt)
02405 return;
02406 pvt->peercapability = capabilities;
02407 pvt->jointcapability = pvt->options.capability & capabilities;
02408 if (prefs) {
02409 memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs));
02410 if (h323debug) {
02411 int i;
02412 for (i = 0; i < 32; ++i) {
02413 if (!prefs->order[i])
02414 break;
02415 ast_log(LOG_DEBUG, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]);
02416 }
02417 }
02418 if (pvt->rtp) {
02419 if (pvt->options.autoframing) {
02420 ast_log(LOG_DEBUG, "Autoframing option set, using peer's packetization settings\n");
02421 ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
02422 } else {
02423 ast_log(LOG_DEBUG, "Autoframing option not set, using ignoring peer's packetization settings\n");
02424 ast_rtp_codec_setpref(pvt->rtp, &pvt->options.prefs);
02425 }
02426 }
02427 }
02428 ast_mutex_unlock(&pvt->lock);
02429 }
02430
02431 static void set_local_capabilities(unsigned call_reference, const char *token)
02432 {
02433 struct oh323_pvt *pvt;
02434 int capability, dtmfmode, pref_codec;
02435 struct ast_codec_pref prefs;
02436
02437 if (h323debug)
02438 ast_log(LOG_DEBUG, "Setting capabilities for connection %s\n", token);
02439
02440 pvt = find_call_locked(call_reference, token);
02441 if (!pvt)
02442 return;
02443 capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
02444 dtmfmode = pvt->options.dtmfmode;
02445 prefs = pvt->options.prefs;
02446 pref_codec = pvt->pref_codec;
02447 ast_mutex_unlock(&pvt->lock);
02448 h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
02449
02450 if (h323debug) {
02451 int i;
02452 for (i = 0; i < 32; i++) {
02453 if (!prefs.order[i])
02454 break;
02455 ast_log(LOG_DEBUG, "local prefs[%d]=%s:%d\n", i, (prefs.order[i] ? ast_getformatname(1 << (prefs.order[i]-1)) : "<none>"), prefs.framing[i]);
02456 }
02457 ast_log(LOG_DEBUG, "Capabilities for connection %s is set\n", token);
02458 }
02459 }
02460
02461 static void *do_monitor(void *data)
02462 {
02463 int res;
02464 int reloading;
02465 struct oh323_pvt *oh323 = NULL;
02466
02467 for(;;) {
02468
02469 ast_mutex_lock(&h323_reload_lock);
02470 reloading = h323_reloading;
02471 h323_reloading = 0;
02472 ast_mutex_unlock(&h323_reload_lock);
02473 if (reloading) {
02474 if (option_verbose > 0) {
02475 ast_verbose(VERBOSE_PREFIX_1 "Reloading H.323\n");
02476 }
02477 h323_do_reload();
02478 }
02479
02480 if (!ast_mutex_trylock(&iflock)) {
02481 #if 1
02482 do {
02483 for (oh323 = iflist; oh323; oh323 = oh323->next) {
02484 if (!ast_mutex_trylock(&oh323->lock)) {
02485 if (oh323->needdestroy) {
02486 __oh323_destroy(oh323);
02487 break;
02488 }
02489 ast_mutex_unlock(&oh323->lock);
02490 }
02491 }
02492 } while ( 0);
02493 #else
02494 restartsearch:
02495 oh323 = iflist;
02496 while(oh323) {
02497 if (!ast_mutex_trylock(&oh323->lock)) {
02498 if (oh323->needdestroy) {
02499 __oh323_destroy(oh323);
02500 goto restartsearch;
02501 }
02502 ast_mutex_unlock(&oh323->lock);
02503 oh323 = oh323->next;
02504 }
02505 }
02506 #endif
02507 ast_mutex_unlock(&iflock);
02508 } else
02509 oh323 = (struct oh323_pvt *)1;
02510 pthread_testcancel();
02511
02512 res = ast_sched_wait(sched);
02513 if ((res < 0) || (res > 1000)) {
02514 res = 1000;
02515 }
02516
02517 if (oh323)
02518 res = 1;
02519 res = ast_io_wait(io, res);
02520 pthread_testcancel();
02521 ast_mutex_lock(&monlock);
02522 if (res >= 0) {
02523 ast_sched_runq(sched);
02524 }
02525 ast_mutex_unlock(&monlock);
02526 }
02527
02528 return NULL;
02529 }
02530
02531 static int restart_monitor(void)
02532 {
02533
02534 if (ast_mutex_lock(&monlock)) {
02535 ast_log(LOG_WARNING, "Unable to lock monitor\n");
02536 return -1;
02537 }
02538 if (monitor_thread == AST_PTHREADT_STOP) {
02539 ast_mutex_unlock(&monlock);
02540 return 0;
02541 }
02542 if (monitor_thread == pthread_self()) {
02543 ast_mutex_unlock(&monlock);
02544 ast_log(LOG_WARNING, "Cannot kill myself\n");
02545 return -1;
02546 }
02547 if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) {
02548
02549 pthread_kill(monitor_thread, SIGURG);
02550 } else {
02551
02552 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
02553 monitor_thread = AST_PTHREADT_NULL;
02554 ast_mutex_unlock(&monlock);
02555 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
02556 return -1;
02557 }
02558 }
02559 ast_mutex_unlock(&monlock);
02560 return 0;
02561 }
02562
02563 static int h323_do_trace(int fd, int argc, char *argv[])
02564 {
02565 if (argc != 4) {
02566 return RESULT_SHOWUSAGE;
02567 }
02568 h323_debug(1, atoi(argv[3]));
02569 ast_cli(fd, "H.323 trace set to level %s\n", argv[2]);
02570 return RESULT_SUCCESS;
02571 }
02572
02573 static int h323_no_trace(int fd, int argc, char *argv[])
02574 {
02575 if (argc < 3 || argc > 4) {
02576 return RESULT_SHOWUSAGE;
02577 }
02578 h323_debug(0,0);
02579 ast_cli(fd, "H.323 trace disabled\n");
02580 return RESULT_SUCCESS;
02581 }
02582
02583 static int h323_do_debug(int fd, int argc, char *argv[])
02584 {
02585 if (argc < 2 || argc > 3) {
02586 return RESULT_SHOWUSAGE;
02587 }
02588 h323debug = 1;
02589 ast_cli(fd, "H.323 debug enabled\n");
02590 return RESULT_SUCCESS;
02591 }
02592
02593 static int h323_no_debug(int fd, int argc, char *argv[])
02594 {
02595 if (argc < 3 || argc > 4) {
02596 return RESULT_SHOWUSAGE;
02597 }
02598 h323debug = 0;
02599 ast_cli(fd, "H.323 debug disabled\n");
02600 return RESULT_SUCCESS;
02601 }
02602
02603 static int h323_gk_cycle(int fd, int argc, char *argv[])
02604 {
02605 if (argc != 3) {
02606 return RESULT_SHOWUSAGE;
02607 }
02608 h323_gk_urq();
02609
02610
02611 if (!gatekeeper_disable) {
02612 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
02613 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
02614 }
02615 }
02616 return RESULT_SUCCESS;
02617 }
02618
02619 static int h323_ep_hangup(int fd, int argc, char *argv[])
02620 {
02621 if (argc != 3) {
02622 return RESULT_SHOWUSAGE;
02623 }
02624 if (h323_soft_hangup(argv[2])) {
02625 ast_verbose(VERBOSE_PREFIX_3 "Hangup succeeded on %s\n", argv[2]);
02626 } else {
02627 ast_verbose(VERBOSE_PREFIX_3 "Hangup failed for %s\n", argv[2]);
02628 }
02629 return RESULT_SUCCESS;
02630 }
02631
02632 static int h323_tokens_show(int fd, int argc, char *argv[])
02633 {
02634 if (argc != 3) {
02635 return RESULT_SHOWUSAGE;
02636 }
02637 h323_show_tokens();
02638 return RESULT_SUCCESS;
02639 }
02640
02641 static int h323_version_show(int fd, int argc, char *argv[])
02642 {
02643 if (argc != 3) {
02644 return RESULT_SHOWUSAGE;
02645 }
02646 h323_show_version();
02647 return RESULT_SUCCESS;
02648 }
02649
02650 static char trace_usage[] =
02651 "Usage: h.323 trace <level num>\n"
02652 " Enables H.323 stack tracing for debugging purposes\n";
02653
02654 static char no_trace_usage[] =
02655 "Usage: h.323 trace off\n"
02656 " Disables H.323 stack tracing for debugging purposes\n";
02657
02658 static char debug_usage[] =
02659 "Usage: h.323 debug\n"
02660 " Enables H.323 debug output\n";
02661
02662 static char no_debug_usage[] =
02663 "Usage: h.323 debug off\n"
02664 " Disables H.323 debug output\n";
02665
02666 static char show_cycle_usage[] =
02667 "Usage: h.323 gk cycle\n"
02668 " Manually re-register with the Gatekeper (Currently Disabled)\n";
02669
02670 static char show_hangup_usage[] =
02671 "Usage: h.323 hangup <token>\n"
02672 " Manually try to hang up call identified by <token>\n";
02673
02674 static char show_tokens_usage[] =
02675 "Usage: h.323 show tokens\n"
02676 " Print out all active call tokens\n";
02677
02678 static char show_version_usage[] =
02679 "Usage: h.323 show version\n"
02680 " Print the version of the H.323 library in use\n";
02681
02682 static char h323_reload_usage[] =
02683 "Usage: h323 reload\n"
02684 " Reloads H.323 configuration from h323.conf\n";
02685
02686 static struct ast_cli_entry cli_h323_no_trace_deprecated = {
02687 { "h.323", "no", "trace", NULL },
02688 h323_no_trace, "Disable H.323 Stack Tracing",
02689 no_trace_usage };
02690
02691 static struct ast_cli_entry cli_h323_no_debug_deprecated = {
02692 { "h.323", "no", "debug", NULL },
02693 h323_no_debug, "Disable H.323 debug",
02694 no_debug_usage };
02695
02696 static struct ast_cli_entry cli_h323_debug_deprecated = {
02697 { "h.323", "debug", NULL },
02698 h323_do_debug, "Enable H.323 debug",
02699 debug_usage };
02700
02701 static struct ast_cli_entry cli_h323_trace_deprecated = {
02702 { "h.323", "trace", NULL },
02703 h323_do_trace, "Enable H.323 Stack Tracing",
02704 trace_usage };
02705
02706 static struct ast_cli_entry cli_h323_gk_cycle_deprecated = {
02707 { "h.323", "gk", "cycle", NULL },
02708 h323_gk_cycle, "Manually re-register with the Gatekeper",
02709 show_cycle_usage };
02710
02711 static struct ast_cli_entry cli_h323[] = {
02712 { { "h323", "set", "trace", NULL },
02713 h323_do_trace, "Enable H.323 Stack Tracing",
02714 trace_usage, NULL, &cli_h323_trace_deprecated },
02715
02716 { { "h323", "set", "trace", "off", NULL },
02717 h323_no_trace, "Disable H.323 Stack Tracing",
02718 no_trace_usage, NULL, &cli_h323_no_trace_deprecated },
02719
02720 { { "h323", "set", "debug", NULL },
02721 h323_do_debug, "Enable H.323 debug",
02722 debug_usage, NULL, &cli_h323_debug_deprecated },
02723
02724 { { "h323", "set", "debug", "off", NULL },
02725 h323_no_debug, "Disable H.323 debug",
02726 no_debug_usage, NULL, &cli_h323_no_debug_deprecated },
02727
02728 { { "h323", "cycle", "gk", NULL },
02729 h323_gk_cycle, "Manually re-register with the Gatekeper",
02730 show_cycle_usage, NULL, &cli_h323_gk_cycle_deprecated },
02731
02732 { { "h323", "hangup", NULL },
02733 h323_ep_hangup, "Manually try to hang up a call",
02734 show_hangup_usage },
02735
02736 { { "h323", "show", "tokens", NULL },
02737 h323_tokens_show, "Show all active call tokens",
02738 show_tokens_usage },
02739
02740 { { "h323", "show", "version", NULL },
02741 h323_version_show, "Show the version of the H.323 library in use",
02742 show_version_usage },
02743 };
02744
02745 static void delete_users(void)
02746 {
02747 int pruned = 0;
02748
02749
02750 ASTOBJ_CONTAINER_WRLOCK(&userl);
02751 ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
02752 ASTOBJ_RDLOCK(iterator);
02753 ASTOBJ_MARK(iterator);
02754 ++pruned;
02755 ASTOBJ_UNLOCK(iterator);
02756 } while (0) );
02757 if (pruned) {
02758 ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
02759 }
02760 ASTOBJ_CONTAINER_UNLOCK(&userl);
02761
02762 ASTOBJ_CONTAINER_WRLOCK(&peerl);
02763 ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
02764 ASTOBJ_RDLOCK(iterator);
02765 ASTOBJ_MARK(iterator);
02766 ASTOBJ_UNLOCK(iterator);
02767 } while (0) );
02768 ASTOBJ_CONTAINER_UNLOCK(&peerl);
02769 }
02770
02771 static void delete_aliases(void)
02772 {
02773 int pruned = 0;
02774
02775
02776 ASTOBJ_CONTAINER_WRLOCK(&aliasl);
02777 ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
02778 ASTOBJ_RDLOCK(iterator);
02779 ASTOBJ_MARK(iterator);
02780 ++pruned;
02781 ASTOBJ_UNLOCK(iterator);
02782 } while (0) );
02783 if (pruned) {
02784 ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
02785 }
02786 ASTOBJ_CONTAINER_UNLOCK(&aliasl);
02787 }
02788
02789 static void prune_peers(void)
02790 {
02791
02792 ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
02793 }
02794
02795 static int reload_config(int is_reload)
02796 {
02797 int format;
02798 struct ast_config *cfg, *ucfg;
02799 struct ast_variable *v;
02800 struct oh323_peer *peer = NULL;
02801 struct oh323_user *user = NULL;
02802 struct oh323_alias *alias = NULL;
02803 struct ast_hostent ahp; struct hostent *hp;
02804 char *cat;
02805 const char *utype;
02806 int is_user, is_peer, is_alias;
02807 char _gatekeeper[100];
02808 int gk_discover, gk_disable, gk_changed;
02809
02810 cfg = ast_config_load(config);
02811
02812
02813 if (!cfg) {
02814 ast_log(LOG_NOTICE, "Unable to load config %s, H.323 disabled\n", config);
02815 return 1;
02816 }
02817
02818 if (is_reload) {
02819 delete_users();
02820 delete_aliases();
02821 prune_peers();
02822 }
02823
02824
02825 if (!h323_end_point_exist()) {
02826 h323_end_point_create();
02827 }
02828 ast_copy_string(_gatekeeper, gatekeeper, sizeof(_gatekeeper));
02829 gk_discover = gatekeeper_discover;
02830 gk_disable = gatekeeper_disable;
02831 memset(&bindaddr, 0, sizeof(bindaddr));
02832 memset(&global_options, 0, sizeof(global_options));
02833 global_options.fastStart = 1;
02834 global_options.h245Tunneling = 1;
02835 global_options.dtmfcodec = 101;
02836 global_options.dtmfmode = H323_DTMF_RFC2833;
02837 global_options.capability = GLOBAL_CAPABILITY;
02838 global_options.bridge = 1;
02839 global_options.autoframing = 0;
02840 strcpy(default_context, "default");
02841 h323_signalling_port = 1720;
02842 gatekeeper_disable = 1;
02843 gatekeeper_discover = 0;
02844 gkroute = 0;
02845 userbyalias = 1;
02846 acceptAnonymous = 1;
02847 tos = 0;
02848
02849
02850 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
02851
02852
02853 ucfg = ast_config_load("users.conf");
02854 if (ucfg) {
02855 struct ast_variable *gen;
02856 int genhas_h323;
02857 const char *has_h323;
02858
02859 genhas_h323 = ast_true(ast_variable_retrieve(ucfg, "general", "hash323"));
02860 gen = ast_variable_browse(ucfg, "general");
02861 for (cat = ast_category_browse(ucfg, NULL); cat; cat = ast_category_browse(ucfg, cat)) {
02862 if (strcasecmp(cat, "general")) {
02863 has_h323 = ast_variable_retrieve(ucfg, cat, "hash323");
02864 if (ast_true(has_h323) || (!has_h323 && genhas_h323)) {
02865 user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
02866 if (user) {
02867 ASTOBJ_CONTAINER_LINK(&userl, user);
02868 ASTOBJ_UNREF(user, oh323_destroy_user);
02869 }
02870 peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
02871 if (peer) {
02872 ASTOBJ_CONTAINER_LINK(&peerl, peer);
02873 ASTOBJ_UNREF(peer, oh323_destroy_peer);
02874 }
02875 }
02876 }
02877 }
02878 ast_config_destroy(ucfg);
02879 }
02880
02881 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
02882
02883 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
02884 continue;
02885
02886 if (!strcasecmp(v->name, "port")) {
02887 h323_signalling_port = (int)strtol(v->value, NULL, 10);
02888 } else if (!strcasecmp(v->name, "bindaddr")) {
02889 if (!(hp = ast_gethostbyname(v->value, &ahp))) {
02890 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
02891 } else {
02892 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
02893 }
02894 } else if (!strcasecmp(v->name, "tos")) {
02895 if (sscanf(v->value, "%30d", &format)) {
02896 tos = format & 0xff;
02897 } else if (!strcasecmp(v->value, "lowdelay")) {
02898 tos = IPTOS_LOWDELAY;
02899 } else if (!strcasecmp(v->value, "throughput")) {
02900 tos = IPTOS_THROUGHPUT;
02901 } else if (!strcasecmp(v->value, "reliability")) {
02902 tos = IPTOS_RELIABILITY;
02903 } else if (!strcasecmp(v->value, "mincost")) {
02904 tos = IPTOS_MINCOST;
02905 } else if (!strcasecmp(v->value, "none")) {
02906 tos = 0;
02907 } else {
02908 ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
02909 }
02910 } else if (!strcasecmp(v->name, "gatekeeper")) {
02911 if (!strcasecmp(v->value, "DISABLE")) {
02912 gatekeeper_disable = 1;
02913 } else if (!strcasecmp(v->value, "DISCOVER")) {
02914 gatekeeper_disable = 0;
02915 gatekeeper_discover = 1;
02916 } else {
02917 gatekeeper_disable = 0;
02918 ast_copy_string(gatekeeper, v->value, sizeof(gatekeeper));
02919 }
02920 } else if (!strcasecmp(v->name, "secret")) {
02921 ast_copy_string(secret, v->value, sizeof(secret));
02922 } else if (!strcasecmp(v->name, "AllowGKRouted")) {
02923 gkroute = ast_true(v->value);
02924 } else if (!strcasecmp(v->name, "context")) {
02925 ast_copy_string(default_context, v->value, sizeof(default_context));
02926 ast_verbose(VERBOSE_PREFIX_2 "Setting default context to %s\n", default_context);
02927 } else if (!strcasecmp(v->name, "UserByAlias")) {
02928 userbyalias = ast_true(v->value);
02929 } else if (!strcasecmp(v->name, "AcceptAnonymous")) {
02930 acceptAnonymous = ast_true(v->value);
02931 } else if (!update_common_options(v, &global_options)) {
02932
02933 }
02934 }
02935
02936 for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
02937 if (strcasecmp(cat, "general")) {
02938 utype = ast_variable_retrieve(cfg, cat, "type");
02939 if (utype) {
02940 is_user = is_peer = is_alias = 0;
02941 if (!strcasecmp(utype, "user"))
02942 is_user = 1;
02943 else if (!strcasecmp(utype, "peer"))
02944 is_peer = 1;
02945 else if (!strcasecmp(utype, "friend"))
02946 is_user = is_peer = 1;
02947 else if (!strcasecmp(utype, "h323") || !strcasecmp(utype, "alias"))
02948 is_alias = 1;
02949 else {
02950 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config);
02951 continue;
02952 }
02953 if (is_user) {
02954 user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
02955 if (user) {
02956 ASTOBJ_CONTAINER_LINK(&userl, user);
02957 ASTOBJ_UNREF(user, oh323_destroy_user);
02958 }
02959 }
02960 if (is_peer) {
02961 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
02962 if (peer) {
02963 ASTOBJ_CONTAINER_LINK(&peerl, peer);
02964 ASTOBJ_UNREF(peer, oh323_destroy_peer);
02965 }
02966 }
02967 if (is_alias) {
02968 alias = build_alias(cat, ast_variable_browse(cfg, cat), NULL, 0);
02969 if (alias) {
02970 ASTOBJ_CONTAINER_LINK(&aliasl, alias);
02971 ASTOBJ_UNREF(alias, oh323_destroy_alias);
02972 }
02973 }
02974 } else {
02975 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
02976 }
02977 }
02978 }
02979 ast_config_destroy(cfg);
02980
02981
02982 ASTOBJ_CONTAINER_WRLOCK(&aliasl);
02983 ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
02984 ASTOBJ_RDLOCK(iterator);
02985 if (h323_set_alias(iterator)) {
02986 ast_log(LOG_ERROR, "Alias %s rejected by endpoint\n", alias->name);
02987 ASTOBJ_UNLOCK(iterator);
02988 continue;
02989 }
02990 ASTOBJ_UNLOCK(iterator);
02991 } while (0) );
02992 ASTOBJ_CONTAINER_UNLOCK(&aliasl);
02993
02994
02995 gk_changed = 0;
02996 if (gatekeeper_disable != gk_disable)
02997 gk_changed = is_reload;
02998 else if(!gatekeeper_disable && (gatekeeper_discover != gk_discover))
02999 gk_changed = is_reload;
03000 else if(!gatekeeper_disable && (strncmp(_gatekeeper, gatekeeper, sizeof(_gatekeeper)) != 0))
03001 gk_changed = is_reload;
03002 if (gk_changed) {
03003 if(!gk_disable)
03004 h323_gk_urq();
03005 if (!gatekeeper_disable) {
03006 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03007 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03008 gatekeeper_disable = 1;
03009 }
03010 }
03011 }
03012 return 0;
03013 }
03014
03015 static int h323_reload(int fd, int argc, char *argv[])
03016 {
03017 ast_mutex_lock(&h323_reload_lock);
03018 if (h323_reloading) {
03019 ast_verbose("Previous H.323 reload not yet done\n");
03020 } else {
03021 h323_reloading = 1;
03022 }
03023 ast_mutex_unlock(&h323_reload_lock);
03024 restart_monitor();
03025 return 0;
03026 }
03027
03028 static int h323_do_reload(void)
03029 {
03030 reload_config(1);
03031 return 0;
03032 }
03033
03034 static int reload(void)
03035 {
03036 if (!sched || !io) {
03037 ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03038 return 0;
03039 }
03040 return h323_reload(0, 0, NULL);
03041 }
03042
03043 static struct ast_cli_entry cli_h323_reload =
03044 { { "h.323", "reload", NULL },
03045 h323_reload, "Reload H.323 configuration",
03046 h323_reload_usage
03047 };
03048
03049 static enum ast_rtp_get_result oh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
03050 {
03051 struct oh323_pvt *pvt;
03052 enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
03053
03054 if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
03055 return res;
03056
03057 ast_mutex_lock(&pvt->lock);
03058 if (pvt->rtp && pvt->options.bridge) {
03059 *rtp = pvt->rtp;
03060 res = AST_RTP_TRY_NATIVE;
03061 }
03062 ast_mutex_unlock(&pvt->lock);
03063
03064 return res;
03065 }
03066
03067 static enum ast_rtp_get_result oh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
03068 {
03069 return AST_RTP_GET_FAILED;
03070 }
03071
03072 static char *convertcap(int cap)
03073 {
03074 switch (cap) {
03075 case AST_FORMAT_G723_1:
03076 return "G.723";
03077 case AST_FORMAT_GSM:
03078 return "GSM";
03079 case AST_FORMAT_ULAW:
03080 return "ULAW";
03081 case AST_FORMAT_ALAW:
03082 return "ALAW";
03083 case AST_FORMAT_G722:
03084 return "G.722";
03085 case AST_FORMAT_ADPCM:
03086 return "G.728";
03087 case AST_FORMAT_G729A:
03088 return "G.729";
03089 case AST_FORMAT_SPEEX:
03090 return "SPEEX";
03091 case AST_FORMAT_ILBC:
03092 return "ILBC";
03093 default:
03094 ast_log(LOG_NOTICE, "Don't know how to deal with mode %d\n", cap);
03095 return NULL;
03096 }
03097 }
03098
03099 static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
03100 {
03101
03102 struct oh323_pvt *pvt;
03103 struct sockaddr_in them;
03104 struct sockaddr_in us;
03105 char *mode;
03106
03107 if (!rtp) {
03108 return 0;
03109 }
03110
03111 mode = convertcap(chan->writeformat);
03112 pvt = (struct oh323_pvt *) chan->tech_pvt;
03113 if (!pvt) {
03114 ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
03115 return -1;
03116 }
03117 ast_rtp_get_peer(rtp, &them);
03118 ast_rtp_get_us(rtp, &us);
03119 #if 0
03120 h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
03121 #endif
03122 return 0;
03123 }
03124
03125 static struct ast_rtp_protocol oh323_rtp = {
03126 .type = "H323",
03127 .get_rtp_info = oh323_get_rtp_peer,
03128 .get_vrtp_info = oh323_get_vrtp_peer,
03129 .set_rtp_peer = oh323_set_rtp_peer,
03130 };
03131
03132 static enum ast_module_load_result load_module(void)
03133 {
03134 int res;
03135
03136 h323debug = 0;
03137 sched = sched_context_create();
03138 if (!sched) {
03139 ast_log(LOG_WARNING, "Unable to create schedule context\n");
03140 return AST_MODULE_LOAD_FAILURE;
03141 }
03142 io = io_context_create();
03143 if (!io) {
03144 ast_log(LOG_WARNING, "Unable to create I/O context\n");
03145 return AST_MODULE_LOAD_FAILURE;
03146 }
03147 ast_cli_register(&cli_h323_reload);
03148 ASTOBJ_CONTAINER_INIT(&userl);
03149 ASTOBJ_CONTAINER_INIT(&peerl);
03150 ASTOBJ_CONTAINER_INIT(&aliasl);
03151 res = reload_config(0);
03152 if (res) {
03153
03154 ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03155 ast_cli_unregister(&cli_h323_reload);
03156 io_context_destroy(io);
03157 io = NULL;
03158 sched_context_destroy(sched);
03159 sched = NULL;
03160 ASTOBJ_CONTAINER_DESTROY(&userl);
03161 ASTOBJ_CONTAINER_DESTROY(&peerl);
03162 ASTOBJ_CONTAINER_DESTROY(&aliasl);
03163 return AST_MODULE_LOAD_DECLINE;
03164 } else {
03165
03166 if (ast_channel_register(&oh323_tech)) {
03167 ast_log(LOG_ERROR, "Unable to register channel class 'H323'\n");
03168 ast_cli_unregister(&cli_h323_reload);
03169 h323_end_process();
03170 io_context_destroy(io);
03171 sched_context_destroy(sched);
03172
03173 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03174 ASTOBJ_CONTAINER_DESTROY(&userl);
03175 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03176 ASTOBJ_CONTAINER_DESTROY(&peerl);
03177 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03178 ASTOBJ_CONTAINER_DESTROY(&aliasl);
03179
03180 return AST_MODULE_LOAD_FAILURE;
03181 }
03182 ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03183
03184 ast_rtp_proto_register(&oh323_rtp);
03185
03186
03187 h323_callback_register(setup_incoming_call,
03188 setup_outgoing_call,
03189 external_rtp_create,
03190 setup_rtp_connection,
03191 cleanup_connection,
03192 chan_ringing,
03193 connection_made,
03194 receive_digit,
03195 answer_call,
03196 progress,
03197 set_dtmf_payload,
03198 hangup_connection,
03199 set_local_capabilities,
03200 set_peer_capabilities);
03201
03202 if (h323_start_listener(h323_signalling_port, bindaddr)) {
03203 ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
03204 ast_rtp_proto_unregister(&oh323_rtp);
03205 ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03206 ast_cli_unregister(&cli_h323_reload);
03207 h323_end_process();
03208 io_context_destroy(io);
03209 sched_context_destroy(sched);
03210
03211 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03212 ASTOBJ_CONTAINER_DESTROY(&userl);
03213 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03214 ASTOBJ_CONTAINER_DESTROY(&peerl);
03215 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03216 ASTOBJ_CONTAINER_DESTROY(&aliasl);
03217
03218 return AST_MODULE_LOAD_DECLINE;
03219 }
03220
03221 if (!gatekeeper_disable) {
03222 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03223 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03224 gatekeeper_disable = 1;
03225 res = AST_MODULE_LOAD_SUCCESS;
03226 }
03227 }
03228
03229 restart_monitor();
03230 }
03231 return res;
03232 }
03233
03234 static int unload_module(void)
03235 {
03236 struct oh323_pvt *p, *pl;
03237
03238
03239 ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03240 ast_cli_unregister(&cli_h323_reload);
03241
03242 ast_channel_unregister(&oh323_tech);
03243 ast_rtp_proto_unregister(&oh323_rtp);
03244
03245 if (!ast_mutex_lock(&iflock)) {
03246
03247 p = iflist;
03248 while(p) {
03249 if (p->owner) {
03250 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
03251 }
03252 p = p->next;
03253 }
03254 iflist = NULL;
03255 ast_mutex_unlock(&iflock);
03256 } else {
03257 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03258 return -1;
03259 }
03260 if (!ast_mutex_lock(&monlock)) {
03261 if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
03262 if (monitor_thread != pthread_self()) {
03263 pthread_cancel(monitor_thread);
03264 }
03265 pthread_kill(monitor_thread, SIGURG);
03266 pthread_join(monitor_thread, NULL);
03267 }
03268 monitor_thread = AST_PTHREADT_STOP;
03269 ast_mutex_unlock(&monlock);
03270 } else {
03271 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
03272 return -1;
03273 }
03274 if (!ast_mutex_lock(&iflock)) {
03275
03276 p = iflist;
03277 while(p) {
03278 pl = p;
03279 p = p->next;
03280
03281 ast_mutex_destroy(&pl->lock);
03282 free(pl);
03283 }
03284 iflist = NULL;
03285 ast_mutex_unlock(&iflock);
03286 } else {
03287 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03288 return -1;
03289 }
03290 if (!gatekeeper_disable)
03291 h323_gk_urq();
03292 h323_end_process();
03293 if (io)
03294 io_context_destroy(io);
03295 if (sched)
03296 sched_context_destroy(sched);
03297
03298 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03299 ASTOBJ_CONTAINER_DESTROY(&userl);
03300 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03301 ASTOBJ_CONTAINER_DESTROY(&peerl);
03302 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03303 ASTOBJ_CONTAINER_DESTROY(&aliasl);
03304
03305 return 0;
03306 }
03307
03308 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "The NuFone Network's OpenH323 Channel Driver",
03309 .load = load_module,
03310 .unload = unload_module,
03311 .reload = reload,
03312 );