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