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