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