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