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