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: 346762 $")
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 format_t oldformat;
01761 struct oh323_pvt *pvt;
01762 struct ast_channel *tmpc = NULL;
01763 char *dest = (char *)data;
01764 char *ext, *host;
01765 char *h323id = NULL;
01766 char tmp[256], tmp1[256];
01767
01768 if (h323debug)
01769 ast_debug(1, "type=%s, format=%s, data=%s.\n", type, ast_getformatname_multiple(tmp, sizeof(tmp), format), (char *)data);
01770
01771 pvt = oh323_alloc(0);
01772 if (!pvt) {
01773 ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data);
01774 return NULL;
01775 }
01776 oldformat = format;
01777 format &= AST_FORMAT_AUDIO_MASK;
01778 if (!format) {
01779 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), format));
01780 oh323_destroy(pvt);
01781 if (cause)
01782 *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
01783 return NULL;
01784 }
01785 ast_copy_string(tmp, dest, sizeof(tmp));
01786 host = strchr(tmp, '@');
01787 if (host) {
01788 *host = '\0';
01789 host++;
01790 ext = tmp;
01791 } else {
01792 ext = strrchr(tmp, '/');
01793 if (ext)
01794 *ext++ = '\0';
01795 host = tmp;
01796 }
01797 strtok_r(host, "/", &(h323id));
01798 if (!ast_strlen_zero(h323id)) {
01799 h323_set_id(h323id);
01800 }
01801 if (ext) {
01802 ast_copy_string(pvt->exten, ext, sizeof(pvt->exten));
01803 }
01804 if (h323debug)
01805 ast_debug(1, "Extension: %s Host: %s\n", pvt->exten, host);
01806
01807 if (gatekeeper_disable) {
01808 if (create_addr(pvt, host)) {
01809 oh323_destroy(pvt);
01810 if (cause)
01811 *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01812 return NULL;
01813 }
01814 }
01815 else {
01816 memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01817 pvt->jointcapability = pvt->options.capability;
01818 if (pvt->options.dtmfmode) {
01819 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01820 pvt->nonCodecCapability |= AST_RTP_DTMF;
01821 } else {
01822 pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01823 }
01824 }
01825 }
01826
01827 ast_mutex_lock(&caplock);
01828
01829 snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
01830 tmp1[sizeof(tmp1)-1] = '\0';
01831 ast_mutex_unlock(&caplock);
01832
01833 ast_mutex_lock(&pvt->lock);
01834 tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1, requestor ? requestor->linkedid : NULL);
01835 ast_mutex_unlock(&pvt->lock);
01836 if (!tmpc) {
01837 oh323_destroy(pvt);
01838 if (cause)
01839 *cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
01840 }
01841 ast_update_use_count();
01842 restart_monitor();
01843 return tmpc;
01844 }
01845
01846
01847 static struct oh323_alias *find_alias(const char *source_aliases, int realtime)
01848 {
01849 struct oh323_alias *a;
01850
01851 a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
01852
01853 if (!a && realtime)
01854 a = realtime_alias(source_aliases);
01855
01856 return a;
01857 }
01858
01859
01860
01861
01862
01863 static int receive_digit(unsigned call_reference, char digit, const char *token, int duration)
01864 {
01865 struct oh323_pvt *pvt;
01866 int res;
01867
01868 pvt = find_call_locked(call_reference, token);
01869 if (!pvt) {
01870 ast_log(LOG_ERROR, "Received digit '%c' (%u ms) for call %s without private structure\n", digit, duration, token);
01871 return -1;
01872 }
01873 if (h323debug)
01874 ast_log(LOG_DTMF, "Received %s digit '%c' (%u ms) for call %s\n", (digit == ' ' ? "update for" : "new"), (digit == ' ' ? pvt->curDTMF : digit), duration, token);
01875
01876 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01877 if (digit == '!')
01878 res = ast_queue_control(pvt->owner, AST_CONTROL_FLASH);
01879 else {
01880 struct ast_frame f = {
01881 .frametype = AST_FRAME_DTMF_END,
01882 .subclass.integer = digit,
01883 .samples = duration * 8,
01884 .len = duration,
01885 .src = "SEND_DIGIT",
01886 };
01887 if (digit == ' ') {
01888 f.subclass.integer = pvt->curDTMF;
01889 AST_SCHED_DEL(sched, pvt->DTMFsched);
01890 } else {
01891 if (pvt->DTMFsched >= 0) {
01892
01893 AST_SCHED_DEL(sched, pvt->DTMFsched);
01894 f.subclass.integer = pvt->curDTMF;
01895 f.samples = f.len = 0;
01896 ast_queue_frame(pvt->owner, &f);
01897
01898 f.subclass.integer = digit;
01899 f.samples = duration * 8;
01900 f.len = duration;
01901 }
01902 if (duration) {
01903 f.frametype = AST_FRAME_DTMF_BEGIN;
01904 pvt->DTMFsched = ast_sched_add(sched, duration, oh323_simulate_dtmf_end, pvt);
01905 if (h323debug)
01906 ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", duration, pvt->DTMFsched);
01907 }
01908 pvt->curDTMF = digit;
01909 }
01910 res = ast_queue_frame(pvt->owner, &f);
01911 }
01912 ast_channel_unlock(pvt->owner);
01913 } else {
01914 if (digit == '!')
01915 pvt->newcontrol = AST_CONTROL_FLASH;
01916 else {
01917 pvt->newduration = duration;
01918 pvt->newdigit = digit;
01919 }
01920 res = 0;
01921 }
01922 ast_mutex_unlock(&pvt->lock);
01923 return res;
01924 }
01925
01926
01927
01928
01929
01930
01931 static struct rtp_info *external_rtp_create(unsigned call_reference, const char * token)
01932 {
01933 struct oh323_pvt *pvt;
01934 struct sockaddr_in us;
01935 struct rtp_info *info;
01936
01937 info = ast_calloc(1, sizeof(*info));
01938 if (!info) {
01939 ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
01940 return NULL;
01941 }
01942 pvt = find_call_locked(call_reference, token);
01943 if (!pvt) {
01944 ast_free(info);
01945 ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
01946 return NULL;
01947 }
01948 if (!pvt->rtp)
01949 __oh323_rtp_create(pvt);
01950 if (!pvt->rtp) {
01951 ast_mutex_unlock(&pvt->lock);
01952 ast_free(info);
01953 ast_log(LOG_ERROR, "No RTP stream is available for call %s (%d)", token, call_reference);
01954 return NULL;
01955 }
01956
01957 {
01958 struct ast_sockaddr tmp;
01959
01960 ast_rtp_instance_get_local_address(pvt->rtp, &tmp);
01961 ast_sockaddr_to_sin(&tmp, &us);
01962 }
01963 ast_mutex_unlock(&pvt->lock);
01964
01965 ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
01966 info->port = ntohs(us.sin_port);
01967 if (h323debug)
01968 ast_debug(1, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
01969 return info;
01970 }
01971
01972
01973
01974
01975
01976
01977 static void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt)
01978 {
01979 struct oh323_pvt *pvt;
01980 struct sockaddr_in them;
01981 int nativeformats_changed;
01982 enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE;
01983
01984 if (h323debug)
01985 ast_debug(1, "Setting up RTP connection for %s\n", token);
01986
01987
01988 pvt = find_call_locked(call_reference, token);
01989 if (!pvt) {
01990 ast_log(LOG_ERROR, "Something is wrong: rtp\n");
01991 return;
01992 }
01993 if (pvt->alreadygone) {
01994 ast_mutex_unlock(&pvt->lock);
01995 return;
01996 }
01997
01998 if (!pvt->rtp)
01999 __oh323_rtp_create(pvt);
02000
02001 if ((pt == 2) && (pvt->jointcapability & AST_FORMAT_G726_AAL2)) {
02002 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);
02003 }
02004
02005 them.sin_family = AF_INET;
02006
02007 them.sin_addr.s_addr = inet_addr(remoteIp);
02008 them.sin_port = htons(remotePort);
02009
02010 if (them.sin_addr.s_addr) {
02011 {
02012 struct ast_sockaddr tmp;
02013
02014 ast_sockaddr_from_sin(&tmp, &them);
02015 ast_rtp_instance_set_remote_address(pvt->rtp, &tmp);
02016 }
02017 if (pvt->recvonly) {
02018 pvt->recvonly = 0;
02019 rtp_change = NEED_UNHOLD;
02020 }
02021 } else {
02022 ast_rtp_instance_stop(pvt->rtp);
02023 if (!pvt->recvonly) {
02024 pvt->recvonly = 1;
02025 rtp_change = NEED_HOLD;
02026 }
02027 }
02028
02029
02030 nativeformats_changed = 0;
02031 if (pt != 128 && pvt->rtp) {
02032 struct ast_rtp_payload_type rtptype = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(pvt->rtp), pt);
02033 if (h323debug)
02034 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);
02035 if (pvt->nativeformats != rtptype.code) {
02036 pvt->nativeformats = rtptype.code;
02037 nativeformats_changed = 1;
02038 }
02039 } else if (h323debug)
02040 ast_log(LOG_NOTICE, "Payload type is unknown, formats isn't changed\n");
02041
02042
02043 if (nativeformats_changed || pvt->options.progress_audio || (rtp_change != NEED_NONE)) {
02044 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02045
02046 if (pvt->owner->nativeformats != pvt->nativeformats) {
02047 if (h323debug) {
02048 char tmp[256], tmp2[256];
02049 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));
02050 }
02051 pvt->owner->nativeformats = pvt->nativeformats;
02052 ast_set_read_format(pvt->owner, pvt->owner->readformat);
02053 ast_set_write_format(pvt->owner, pvt->owner->writeformat);
02054 }
02055 if (pvt->options.progress_audio)
02056 ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);
02057 switch (rtp_change) {
02058 case NEED_HOLD:
02059 ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02060 break;
02061 case NEED_UNHOLD:
02062 ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02063 break;
02064 default:
02065 break;
02066 }
02067 ast_channel_unlock(pvt->owner);
02068 }
02069 else {
02070 if (pvt->options.progress_audio)
02071 pvt->newcontrol = AST_CONTROL_PROGRESS;
02072 else if (rtp_change == NEED_HOLD)
02073 pvt->newcontrol = AST_CONTROL_HOLD;
02074 else if (rtp_change == NEED_UNHOLD)
02075 pvt->newcontrol = AST_CONTROL_UNHOLD;
02076 if (h323debug)
02077 ast_debug(1, "RTP connection preparation for %s is pending...\n", token);
02078 }
02079 }
02080 ast_mutex_unlock(&pvt->lock);
02081
02082 if (h323debug)
02083 ast_debug(1, "RTP connection prepared for %s\n", token);
02084
02085 return;
02086 }
02087
02088
02089
02090
02091
02092 static void connection_made(unsigned call_reference, const char *token)
02093 {
02094 struct oh323_pvt *pvt;
02095
02096 if (h323debug)
02097 ast_debug(1, "Call %s answered\n", token);
02098
02099 pvt = find_call_locked(call_reference, token);
02100 if (!pvt) {
02101 ast_log(LOG_ERROR, "Something is wrong: connection\n");
02102 return;
02103 }
02104
02105
02106 if (!pvt->outgoing) {
02107 ast_mutex_unlock(&pvt->lock);
02108 return;
02109 }
02110
02111 if (!pvt->connection_established) {
02112 pvt->connection_established = 1;
02113 update_state(pvt, -1, AST_CONTROL_ANSWER);
02114 }
02115 ast_mutex_unlock(&pvt->lock);
02116 return;
02117 }
02118
02119 static int progress(unsigned call_reference, const char *token, int inband)
02120 {
02121 struct oh323_pvt *pvt;
02122
02123 if (h323debug)
02124 ast_debug(1, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
02125
02126 pvt = find_call_locked(call_reference, token);
02127 if (!pvt) {
02128 ast_log(LOG_ERROR, "Private structure not found in progress.\n");
02129 return -1;
02130 }
02131 if (!pvt->owner) {
02132 ast_mutex_unlock(&pvt->lock);
02133 ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");
02134 return -1;
02135 }
02136 update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));
02137 ast_mutex_unlock(&pvt->lock);
02138
02139 return 0;
02140 }
02141
02142
02143
02144
02145
02146
02147 static call_options_t *setup_incoming_call(call_details_t *cd)
02148 {
02149 struct oh323_pvt *pvt;
02150 struct oh323_user *user = NULL;
02151 struct oh323_alias *alias = NULL;
02152
02153 if (h323debug)
02154 ast_debug(1, "Setting up incoming call for %s\n", cd->call_token);
02155
02156
02157 pvt = oh323_alloc(cd->call_reference);
02158
02159 if (!pvt) {
02160 ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
02161 cleanup_call_details(cd);
02162 return NULL;
02163 }
02164
02165
02166 memcpy(&pvt->cd, cd, sizeof(pvt->cd));
02167 memcpy(&pvt->options, &global_options, sizeof(pvt->options));
02168 pvt->jointcapability = pvt->options.capability;
02169
02170 if (h323debug) {
02171 ast_verb(3, "Setting up Call\n");
02172 ast_verb(3, " \tCall token: [%s]\n", pvt->cd.call_token);
02173 ast_verb(3, " \tCalling party name: [%s]\n", pvt->cd.call_source_name);
02174 ast_verb(3, " \tCalling party number: [%s]\n", pvt->cd.call_source_e164);
02175 ast_verb(3, " \tCalled party name: [%s]\n", pvt->cd.call_dest_alias);
02176 ast_verb(3, " \tCalled party number: [%s]\n", pvt->cd.call_dest_e164);
02177 if (pvt->cd.redirect_reason >= 0)
02178 ast_verb(3, " \tRedirecting party number: [%s] (reason %d)\n", pvt->cd.redirect_number, pvt->cd.redirect_reason);
02179 ast_verb(3, " \tCalling party IP: [%s]\n", pvt->cd.sourceIp);
02180 }
02181
02182
02183 if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && !gatekeeper_disable) {
02184 if (!ast_strlen_zero(cd->call_dest_e164)) {
02185 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02186 ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02187 } else {
02188 alias = find_alias(cd->call_dest_alias, 1);
02189 if (!alias) {
02190 ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias);
02191 oh323_destroy(pvt);
02192 return NULL;
02193 }
02194 ast_copy_string(pvt->exten, alias->name, sizeof(pvt->exten));
02195 ast_copy_string(pvt->context, alias->context, sizeof(pvt->context));
02196 }
02197 } else {
02198
02199
02200 user = find_user(cd, 1);
02201 if (!user) {
02202 if (!acceptAnonymous) {
02203 ast_log(LOG_NOTICE, "Anonymous call from '%s@%s' rejected\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02204 oh323_destroy(pvt);
02205 return NULL;
02206 }
02207 if (ast_strlen_zero(default_context)) {
02208 ast_log(LOG_ERROR, "Call from '%s@%s' rejected due to no default context\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02209 oh323_destroy(pvt);
02210 return NULL;
02211 }
02212 ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02213 if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02214 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02215 } else {
02216 ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02217 }
02218 if (h323debug)
02219 ast_debug(1, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten);
02220 } else {
02221 if (user->host) {
02222 if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) {
02223 if (ast_strlen_zero(user->context)) {
02224 if (ast_strlen_zero(default_context)) {
02225 ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp);
02226 oh323_destroy(pvt);
02227 ASTOBJ_UNREF(user, oh323_destroy_user);
02228 return NULL;
02229 }
02230 ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02231 } else {
02232 ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02233 }
02234 pvt->exten[0] = 'i';
02235 pvt->exten[1] = '\0';
02236 ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp);
02237 oh323_destroy(pvt);
02238 ASTOBJ_UNREF(user, oh323_destroy_user);
02239 return NULL;
02240 }
02241 }
02242 ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02243 memcpy(&pvt->options, &user->options, sizeof(pvt->options));
02244 pvt->jointcapability = pvt->options.capability;
02245 if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02246 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02247 } else {
02248 ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02249 }
02250 if (!ast_strlen_zero(user->accountcode)) {
02251 ast_copy_string(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode));
02252 }
02253 if (user->amaflags) {
02254 pvt->amaflags = user->amaflags;
02255 }
02256 ASTOBJ_UNREF(user, oh323_destroy_user);
02257 }
02258 }
02259 return &pvt->options;
02260 }
02261
02262
02263
02264
02265
02266
02267 static int answer_call(unsigned call_reference, const char *token)
02268 {
02269 struct oh323_pvt *pvt;
02270 struct ast_channel *c = NULL;
02271 enum {ext_original, ext_s, ext_i, ext_notexists} try_exten;
02272 char tmp_exten[sizeof(pvt->exten)];
02273
02274 if (h323debug)
02275 ast_debug(1, "Preparing Asterisk to answer for %s\n", token);
02276
02277
02278 pvt = find_call_locked(call_reference, token);
02279 if (!pvt) {
02280 ast_log(LOG_ERROR, "Something is wrong: answer_call\n");
02281 return 0;
02282 }
02283
02284 ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten));
02285
02286
02287 if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) {
02288 if (tmp_exten[0] == 's')
02289 try_exten = ext_s;
02290 else if (tmp_exten[0] == 'i')
02291 try_exten = ext_i;
02292 else
02293 try_exten = ext_original;
02294 } else
02295 try_exten = ext_original;
02296 do {
02297 if (ast_exists_extension(NULL, pvt->context, tmp_exten, 1, NULL))
02298 break;
02299 switch (try_exten) {
02300 case ext_original:
02301 tmp_exten[0] = 's';
02302 tmp_exten[1] = '\0';
02303 try_exten = ext_s;
02304 break;
02305 case ext_s:
02306 tmp_exten[0] = 'i';
02307 try_exten = ext_i;
02308 break;
02309 case ext_i:
02310 try_exten = ext_notexists;
02311 break;
02312 default:
02313 break;
02314 }
02315 } while (try_exten != ext_notexists);
02316
02317
02318 if (try_exten == ext_notexists) {
02319 ast_log(LOG_NOTICE, "Dropping call because extensions '%s', 's' and 'i' doesn't exists in context [%s]\n", pvt->exten, pvt->context);
02320 ast_mutex_unlock(&pvt->lock);
02321 h323_clear_call(token, AST_CAUSE_UNALLOCATED);
02322 return 0;
02323 } else if ((try_exten != ext_original) && (strcmp(pvt->exten, tmp_exten) != 0)) {
02324 if (h323debug)
02325 ast_debug(1, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context);
02326 ast_copy_string(pvt->exten, tmp_exten, sizeof(pvt->exten));
02327 }
02328
02329
02330 c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token, NULL);
02331
02332
02333 ast_mutex_unlock(&pvt->lock);
02334 if (!c) {
02335 ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n");
02336 return 0;
02337 }
02338 return 1;
02339 }
02340
02341
02342
02343
02344
02345
02346 static int setup_outgoing_call(call_details_t *cd)
02347 {
02348
02349 cleanup_call_details(cd);
02350
02351 return 1;
02352 }
02353
02354
02355
02356
02357
02358 static void chan_ringing(unsigned call_reference, const char *token)
02359 {
02360 struct oh323_pvt *pvt;
02361
02362 if (h323debug)
02363 ast_debug(1, "Ringing on %s\n", token);
02364
02365 pvt = find_call_locked(call_reference, token);
02366 if (!pvt) {
02367 ast_log(LOG_ERROR, "Something is wrong: ringing\n");
02368 return;
02369 }
02370 if (!pvt->owner) {
02371 ast_mutex_unlock(&pvt->lock);
02372 ast_log(LOG_ERROR, "Channel has no owner\n");
02373 return;
02374 }
02375 update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING);
02376 ast_mutex_unlock(&pvt->lock);
02377 return;
02378 }
02379
02380
02381
02382
02383
02384 static void cleanup_connection(unsigned call_reference, const char *call_token)
02385 {
02386 struct oh323_pvt *pvt;
02387
02388 if (h323debug)
02389 ast_debug(1, "Cleaning connection to %s\n", call_token);
02390
02391 while (1) {
02392 pvt = find_call_locked(call_reference, call_token);
02393 if (!pvt) {
02394 if (h323debug)
02395 ast_debug(1, "No connection for %s\n", call_token);
02396 return;
02397 }
02398 if (!pvt->owner || !ast_channel_trylock(pvt->owner))
02399 break;
02400 #if 1
02401 ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token);
02402 #ifdef DEBUG_THREADS
02403
02404
02405
02406
02407
02408 #endif
02409 #endif
02410 ast_mutex_unlock(&pvt->lock);
02411 usleep(1);
02412 }
02413 if (pvt->rtp) {
02414
02415 ast_rtp_instance_destroy(pvt->rtp);
02416 pvt->rtp = NULL;
02417 }
02418
02419 if (pvt->vad) {
02420 ast_dsp_free(pvt->vad);
02421 pvt->vad = NULL;
02422 }
02423 cleanup_call_details(&pvt->cd);
02424 pvt->alreadygone = 1;
02425
02426 if (pvt->owner) {
02427 pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02428 ast_queue_hangup(pvt->owner);
02429 ast_channel_unlock(pvt->owner);
02430 }
02431 ast_mutex_unlock(&pvt->lock);
02432 if (h323debug)
02433 ast_debug(1, "Connection to %s cleaned\n", call_token);
02434 return;
02435 }
02436
02437 static void hangup_connection(unsigned int call_reference, const char *token, int cause)
02438 {
02439 struct oh323_pvt *pvt;
02440
02441 if (h323debug)
02442 ast_debug(1, "Hanging up connection to %s with cause %d\n", token, cause);
02443
02444 pvt = find_call_locked(call_reference, token);
02445 if (!pvt) {
02446 if (h323debug)
02447 ast_debug(1, "Connection to %s already cleared\n", token);
02448 return;
02449 }
02450 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02451 pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02452 pvt->owner->hangupcause = pvt->hangupcause = cause;
02453 ast_queue_hangup_with_cause(pvt->owner, cause);
02454 ast_channel_unlock(pvt->owner);
02455 }
02456 else {
02457 pvt->needhangup = 1;
02458 pvt->hangupcause = cause;
02459 if (h323debug)
02460 ast_debug(1, "Hangup for %s is pending\n", token);
02461 }
02462 ast_mutex_unlock(&pvt->lock);
02463 }
02464
02465 static void set_dtmf_payload(unsigned call_reference, const char *token, int payload, int is_cisco)
02466 {
02467 struct oh323_pvt *pvt;
02468
02469 if (h323debug)
02470 ast_debug(1, "Setting %s DTMF payload to %d on %s\n", (is_cisco ? "Cisco" : "RFC2833"), payload, token);
02471
02472 pvt = find_call_locked(call_reference, token);
02473 if (!pvt) {
02474 return;
02475 }
02476 if (pvt->rtp) {
02477 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);
02478 }
02479 pvt->dtmf_pt[is_cisco ? 1 : 0] = payload;
02480 ast_mutex_unlock(&pvt->lock);
02481 if (h323debug)
02482 ast_debug(1, "DTMF payload on %s set to %d\n", token, payload);
02483 }
02484
02485 static void set_peer_capabilities(unsigned call_reference, const char *token, int capabilities, struct ast_codec_pref *prefs)
02486 {
02487 struct oh323_pvt *pvt;
02488
02489 if (h323debug)
02490 ast_debug(1, "Got remote capabilities from connection %s\n", token);
02491
02492 pvt = find_call_locked(call_reference, token);
02493 if (!pvt)
02494 return;
02495 pvt->peercapability = capabilities;
02496 pvt->jointcapability = pvt->options.capability & capabilities;
02497 if (prefs) {
02498 memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs));
02499 if (h323debug) {
02500 int i;
02501 for (i = 0; i < 32; ++i) {
02502 if (!prefs->order[i])
02503 break;
02504 ast_debug(1, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]);
02505 }
02506 }
02507 if (pvt->rtp) {
02508 if (pvt->options.autoframing) {
02509 ast_debug(2, "Autoframing option set, using peer's packetization settings\n");
02510 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
02511 } else {
02512 ast_debug(2, "Autoframing option not set, ignoring peer's packetization settings\n");
02513 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->options.prefs);
02514 }
02515 }
02516 }
02517 ast_mutex_unlock(&pvt->lock);
02518 }
02519
02520 static void set_local_capabilities(unsigned call_reference, const char *token)
02521 {
02522 struct oh323_pvt *pvt;
02523 int capability, dtmfmode, pref_codec;
02524 struct ast_codec_pref prefs;
02525
02526 if (h323debug)
02527 ast_debug(1, "Setting capabilities for connection %s\n", token);
02528
02529 pvt = find_call_locked(call_reference, token);
02530 if (!pvt)
02531 return;
02532 capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
02533 dtmfmode = pvt->options.dtmfmode;
02534 prefs = pvt->options.prefs;
02535 pref_codec = pvt->pref_codec;
02536 ast_mutex_unlock(&pvt->lock);
02537 h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
02538
02539 if (h323debug) {
02540 int i;
02541 for (i = 0; i < 32; i++) {
02542 if (!prefs.order[i])
02543 break;
02544 ast_debug(1, "local prefs[%d]=%s:%d\n", i, (prefs.order[i] ? ast_getformatname(1 << (prefs.order[i]-1)) : "<none>"), prefs.framing[i]);
02545 }
02546 ast_debug(1, "Capabilities for connection %s is set\n", token);
02547 }
02548 }
02549
02550 static void remote_hold(unsigned call_reference, const char *token, int is_hold)
02551 {
02552 struct oh323_pvt *pvt;
02553
02554 if (h323debug)
02555 ast_debug(1, "Setting %shold status for connection %s\n", (is_hold ? "" : "un"), token);
02556
02557 pvt = find_call_locked(call_reference, token);
02558 if (!pvt)
02559 return;
02560 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02561 if (is_hold)
02562 ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02563 else
02564 ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02565 ast_channel_unlock(pvt->owner);
02566 }
02567 else {
02568 if (is_hold)
02569 pvt->newcontrol = AST_CONTROL_HOLD;
02570 else
02571 pvt->newcontrol = AST_CONTROL_UNHOLD;
02572 }
02573 ast_mutex_unlock(&pvt->lock);
02574 }
02575
02576 static void *do_monitor(void *data)
02577 {
02578 int res;
02579 int reloading;
02580 struct oh323_pvt *oh323 = NULL;
02581
02582 for(;;) {
02583
02584 ast_mutex_lock(&h323_reload_lock);
02585 reloading = h323_reloading;
02586 h323_reloading = 0;
02587 ast_mutex_unlock(&h323_reload_lock);
02588 if (reloading) {
02589 ast_verb(1, "Reloading H.323\n");
02590 h323_do_reload();
02591 }
02592
02593 if (!ast_mutex_trylock(&iflock)) {
02594 #if 1
02595 do {
02596 for (oh323 = iflist; oh323; oh323 = oh323->next) {
02597 if (!ast_mutex_trylock(&oh323->lock)) {
02598 if (oh323->needdestroy) {
02599 __oh323_destroy(oh323);
02600 break;
02601 }
02602 ast_mutex_unlock(&oh323->lock);
02603 }
02604 }
02605 } while ( 0);
02606 #else
02607 restartsearch:
02608 oh323 = iflist;
02609 while(oh323) {
02610 if (!ast_mutex_trylock(&oh323->lock)) {
02611 if (oh323->needdestroy) {
02612 __oh323_destroy(oh323);
02613 goto restartsearch;
02614 }
02615 ast_mutex_unlock(&oh323->lock);
02616 oh323 = oh323->next;
02617 }
02618 }
02619 #endif
02620 ast_mutex_unlock(&iflock);
02621 } else
02622 oh323 = (struct oh323_pvt *)1;
02623 pthread_testcancel();
02624
02625 res = ast_sched_wait(sched);
02626 if ((res < 0) || (res > 1000)) {
02627 res = 1000;
02628 }
02629
02630 if (oh323)
02631 res = 1;
02632 res = ast_io_wait(io, res);
02633 pthread_testcancel();
02634 ast_mutex_lock(&monlock);
02635 if (res >= 0) {
02636 ast_sched_runq(sched);
02637 }
02638 ast_mutex_unlock(&monlock);
02639 }
02640
02641 return NULL;
02642 }
02643
02644 static int restart_monitor(void)
02645 {
02646
02647 if (ast_mutex_lock(&monlock)) {
02648 ast_log(LOG_WARNING, "Unable to lock monitor\n");
02649 return -1;
02650 }
02651 if (monitor_thread == AST_PTHREADT_STOP) {
02652 ast_mutex_unlock(&monlock);
02653 return 0;
02654 }
02655 if (monitor_thread == pthread_self()) {
02656 ast_mutex_unlock(&monlock);
02657 ast_log(LOG_WARNING, "Cannot kill myself\n");
02658 return -1;
02659 }
02660 if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) {
02661
02662 pthread_kill(monitor_thread, SIGURG);
02663 } else {
02664
02665 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
02666 monitor_thread = AST_PTHREADT_NULL;
02667 ast_mutex_unlock(&monlock);
02668 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
02669 return -1;
02670 }
02671 }
02672 ast_mutex_unlock(&monlock);
02673 return 0;
02674 }
02675
02676 static char *handle_cli_h323_set_trace(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02677 {
02678 switch (cmd) {
02679 case CLI_INIT:
02680 e->command = "h323 set trace [on|off]";
02681 e->usage =
02682 "Usage: h323 set trace (on|off|<trace level>)\n"
02683 " Enable/Disable H.323 stack tracing for debugging purposes\n";
02684 return NULL;
02685 case CLI_GENERATE:
02686 return NULL;
02687 }
02688
02689 if (a->argc != e->args)
02690 return CLI_SHOWUSAGE;
02691 if (!strcasecmp(a->argv[3], "off")) {
02692 h323_debug(0, 0);
02693 ast_cli(a->fd, "H.323 Trace Disabled\n");
02694 } else if (!strcasecmp(a->argv[3], "on")) {
02695 h323_debug(1, 1);
02696 ast_cli(a->fd, "H.323 Trace Enabled\n");
02697 } else {
02698 int tracelevel = atoi(a->argv[3]);
02699 h323_debug(1, tracelevel);
02700 ast_cli(a->fd, "H.323 Trace Enabled (Trace Level: %d)\n", tracelevel);
02701 }
02702 return CLI_SUCCESS;
02703 }
02704
02705 static char *handle_cli_h323_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02706 {
02707 switch (cmd) {
02708 case CLI_INIT:
02709 e->command = "h323 set debug [on|off]";
02710 e->usage =
02711 "Usage: h323 set debug [on|off]\n"
02712 " Enable/Disable H.323 debugging output\n";
02713 return NULL;
02714 case CLI_GENERATE:
02715 return NULL;
02716 }
02717
02718 if (a->argc != e->args)
02719 return CLI_SHOWUSAGE;
02720 if (strcasecmp(a->argv[3], "on") && strcasecmp(a->argv[3], "off"))
02721 return CLI_SHOWUSAGE;
02722
02723 h323debug = (strcasecmp(a->argv[3], "on")) ? 0 : 1;
02724 ast_cli(a->fd, "H.323 Debugging %s\n", h323debug ? "Enabled" : "Disabled");
02725 return CLI_SUCCESS;
02726 }
02727
02728 static char *handle_cli_h323_cycle_gk(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02729 {
02730 switch (cmd) {
02731 case CLI_INIT:
02732 e->command = "h323 cycle gk";
02733 e->usage =
02734 "Usage: h323 cycle gk\n"
02735 " Manually re-register with the Gatekeper (Currently Disabled)\n";
02736 return NULL;
02737 case CLI_GENERATE:
02738 return NULL;
02739 }
02740
02741 if (a->argc != 3)
02742 return CLI_SHOWUSAGE;
02743
02744 h323_gk_urq();
02745
02746
02747 if (!gatekeeper_disable) {
02748 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
02749 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
02750 }
02751 }
02752 return CLI_SUCCESS;
02753 }
02754
02755 static char *handle_cli_h323_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02756 {
02757 switch (cmd) {
02758 case CLI_INIT:
02759 e->command = "h323 hangup";
02760 e->usage =
02761 "Usage: h323 hangup <token>\n"
02762 " Manually try to hang up the call identified by <token>\n";
02763 return NULL;
02764 case CLI_GENERATE:
02765 return NULL;
02766 }
02767
02768 if (a->argc != 3)
02769 return CLI_SHOWUSAGE;
02770 if (h323_soft_hangup(a->argv[2])) {
02771 ast_verb(3, "Hangup succeeded on %s\n", a->argv[2]);
02772 } else {
02773 ast_verb(3, "Hangup failed for %s\n", a->argv[2]);
02774 }
02775 return CLI_SUCCESS;
02776 }
02777
02778 static char *handle_cli_h323_show_tokens(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02779 {
02780 switch (cmd) {
02781 case CLI_INIT:
02782 e->command = "h323 show tokens";
02783 e->usage =
02784 "Usage: h323 show tokens\n"
02785 " Print out all active call tokens\n";
02786 return NULL;
02787 case CLI_GENERATE:
02788 return NULL;
02789 }
02790
02791 if (a->argc != 3)
02792 return CLI_SHOWUSAGE;
02793
02794 h323_show_tokens();
02795
02796 return CLI_SUCCESS;
02797 }
02798
02799 static char *handle_cli_h323_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02800 {
02801 switch (cmd) {
02802 case CLI_INIT:
02803 e->command = "h323 show version";
02804 e->usage =
02805 "Usage: h323 show version\n"
02806 " Show the version of the H.323 library in use\n";
02807 return NULL;
02808 case CLI_GENERATE:
02809 return NULL;
02810 }
02811
02812 if (a->argc != 3)
02813 return CLI_SHOWUSAGE;
02814
02815 h323_show_version();
02816
02817 return CLI_SUCCESS;
02818 }
02819
02820 static struct ast_cli_entry cli_h323[] = {
02821 AST_CLI_DEFINE(handle_cli_h323_set_trace, "Enable/Disable H.323 Stack Tracing"),
02822 AST_CLI_DEFINE(handle_cli_h323_set_debug, "Enable/Disable H.323 Debugging"),
02823 AST_CLI_DEFINE(handle_cli_h323_cycle_gk, "Manually re-register with the Gatekeper"),
02824 AST_CLI_DEFINE(handle_cli_h323_hangup, "Manually try to hang up a call"),
02825 AST_CLI_DEFINE(handle_cli_h323_show_tokens, "Show all active call tokens"),
02826 AST_CLI_DEFINE(handle_cli_h323_show_version, "Show the version of the H.323 library in use"),
02827 };
02828
02829 static void delete_users(void)
02830 {
02831 int pruned = 0;
02832
02833
02834 ASTOBJ_CONTAINER_WRLOCK(&userl);
02835 ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
02836 ASTOBJ_RDLOCK(iterator);
02837 ASTOBJ_MARK(iterator);
02838 ++pruned;
02839 ASTOBJ_UNLOCK(iterator);
02840 } while (0) );
02841 if (pruned) {
02842 ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
02843 }
02844 ASTOBJ_CONTAINER_UNLOCK(&userl);
02845
02846 ASTOBJ_CONTAINER_WRLOCK(&peerl);
02847 ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
02848 ASTOBJ_RDLOCK(iterator);
02849 ASTOBJ_MARK(iterator);
02850 ASTOBJ_UNLOCK(iterator);
02851 } while (0) );
02852 ASTOBJ_CONTAINER_UNLOCK(&peerl);
02853 }
02854
02855 static void delete_aliases(void)
02856 {
02857 int pruned = 0;
02858
02859
02860 ASTOBJ_CONTAINER_WRLOCK(&aliasl);
02861 ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
02862 ASTOBJ_RDLOCK(iterator);
02863 ASTOBJ_MARK(iterator);
02864 ++pruned;
02865 ASTOBJ_UNLOCK(iterator);
02866 } while (0) );
02867 if (pruned) {
02868 ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
02869 }
02870 ASTOBJ_CONTAINER_UNLOCK(&aliasl);
02871 }
02872
02873 static void prune_peers(void)
02874 {
02875
02876 ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
02877 }
02878
02879 static int reload_config(int is_reload)
02880 {
02881 struct ast_config *cfg, *ucfg;
02882 struct ast_variable *v;
02883 struct oh323_peer *peer = NULL;
02884 struct oh323_user *user = NULL;
02885 struct oh323_alias *alias = NULL;
02886 struct ast_hostent ahp; struct hostent *hp;
02887 char *cat;
02888 const char *utype;
02889 int is_user, is_peer, is_alias;
02890 char _gatekeeper[100];
02891 int gk_discover, gk_disable, gk_changed;
02892 struct ast_flags config_flags = { is_reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02893
02894 cfg = ast_config_load(config, config_flags);
02895
02896
02897 if (!cfg) {
02898 ast_log(LOG_NOTICE, "Unable to load config %s, H.323 disabled\n", config);
02899 return 1;
02900 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
02901 ucfg = ast_config_load("users.conf", config_flags);
02902 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
02903 return 0;
02904 } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
02905 ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Aborting.\n");
02906 return 0;
02907 }
02908 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
02909 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
02910 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
02911 ast_config_destroy(ucfg);
02912 return 0;
02913 }
02914 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02915 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
02916 return 0;
02917 } else {
02918 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
02919 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
02920 ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Aborting.\n");
02921 ast_config_destroy(cfg);
02922 return 0;
02923 }
02924 }
02925
02926 if (is_reload) {
02927 delete_users();
02928 delete_aliases();
02929 prune_peers();
02930 }
02931
02932
02933 if (!h323_end_point_exist()) {
02934 h323_end_point_create();
02935 }
02936 ast_copy_string(_gatekeeper, gatekeeper, sizeof(_gatekeeper));
02937 gk_discover = gatekeeper_discover;
02938 gk_disable = gatekeeper_disable;
02939 memset(&bindaddr, 0, sizeof(bindaddr));
02940 memset(&global_options, 0, sizeof(global_options));
02941 global_options.fastStart = 1;
02942 global_options.h245Tunneling = 1;
02943 global_options.dtmfcodec[0] = H323_DTMF_RFC2833_PT;
02944 global_options.dtmfcodec[1] = H323_DTMF_CISCO_PT;
02945 global_options.dtmfmode = 0;
02946 global_options.holdHandling = 0;
02947 global_options.capability = GLOBAL_CAPABILITY;
02948 global_options.bridge = 1;
02949 global_options.autoframing = 0;
02950 strcpy(default_context, "default");
02951 h323_signalling_port = 1720;
02952 gatekeeper_disable = 1;
02953 gatekeeper_discover = 0;
02954 gkroute = 0;
02955 userbyalias = 1;
02956 acceptAnonymous = 1;
02957 tos = 0;
02958 cos = 0;
02959
02960
02961 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
02962
02963 if (ucfg) {
02964 struct ast_variable *gen;
02965 int genhas_h323;
02966 const char *has_h323;
02967
02968 genhas_h323 = ast_true(ast_variable_retrieve(ucfg, "general", "hash323"));
02969 gen = ast_variable_browse(ucfg, "general");
02970 for (cat = ast_category_browse(ucfg, NULL); cat; cat = ast_category_browse(ucfg, cat)) {
02971 if (strcasecmp(cat, "general")) {
02972 has_h323 = ast_variable_retrieve(ucfg, cat, "hash323");
02973 if (ast_true(has_h323) || (!has_h323 && genhas_h323)) {
02974 user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
02975 if (user) {
02976 ASTOBJ_CONTAINER_LINK(&userl, user);
02977 ASTOBJ_UNREF(user, oh323_destroy_user);
02978 }
02979 peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
02980 if (peer) {
02981 ASTOBJ_CONTAINER_LINK(&peerl, peer);
02982 ASTOBJ_UNREF(peer, oh323_destroy_peer);
02983 }
02984 }
02985 }
02986 }
02987 ast_config_destroy(ucfg);
02988 }
02989
02990 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
02991
02992 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
02993 continue;
02994
02995 if (!strcasecmp(v->name, "port")) {
02996 h323_signalling_port = (int)strtol(v->value, NULL, 10);
02997 } else if (!strcasecmp(v->name, "bindaddr")) {
02998 if (!(hp = ast_gethostbyname(v->value, &ahp))) {
02999 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
03000 } else {
03001 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
03002 }
03003 } else if (!strcasecmp(v->name, "tos")) {
03004 ast_log(LOG_WARNING, "The \"tos\" setting is deprecated in this version of Asterisk. Please change to \"tos_audio\".\n");
03005 if (ast_str2tos(v->value, &tos)) {
03006 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
03007 }
03008 } else if (!strcasecmp(v->name, "tos_audio")) {
03009 if (ast_str2tos(v->value, &tos)) {
03010 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
03011 }
03012 } else if (!strcasecmp(v->name, "cos")) {
03013 ast_log(LOG_WARNING, "The \"cos\" setting is deprecated in this version of Asterisk. Please change to \"cos_audio\".\n");
03014 if (ast_str2cos(v->value, &cos)) {
03015 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
03016 }
03017 } else if (!strcasecmp(v->name, "cos_audio")) {
03018 if (ast_str2cos(v->value, &cos)) {
03019 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
03020 }
03021 } else if (!strcasecmp(v->name, "gatekeeper")) {
03022 if (!strcasecmp(v->value, "DISABLE")) {
03023 gatekeeper_disable = 1;
03024 } else if (!strcasecmp(v->value, "DISCOVER")) {
03025 gatekeeper_disable = 0;
03026 gatekeeper_discover = 1;
03027 } else {
03028 gatekeeper_disable = 0;
03029 ast_copy_string(gatekeeper, v->value, sizeof(gatekeeper));
03030 }
03031 } else if (!strcasecmp(v->name, "secret")) {
03032 ast_copy_string(secret, v->value, sizeof(secret));
03033 } else if (!strcasecmp(v->name, "AllowGKRouted")) {
03034 gkroute = ast_true(v->value);
03035 } else if (!strcasecmp(v->name, "context")) {
03036 ast_copy_string(default_context, v->value, sizeof(default_context));
03037 ast_verb(2, "Setting default context to %s\n", default_context);
03038 } else if (!strcasecmp(v->name, "UserByAlias")) {
03039 userbyalias = ast_true(v->value);
03040 } else if (!strcasecmp(v->name, "AcceptAnonymous")) {
03041 acceptAnonymous = ast_true(v->value);
03042 } else if (!update_common_options(v, &global_options)) {
03043
03044 }
03045 }
03046 if (!global_options.dtmfmode)
03047 global_options.dtmfmode = H323_DTMF_RFC2833;
03048 if (global_options.holdHandling == ~0)
03049 global_options.holdHandling = 0;
03050 else if (!global_options.holdHandling)
03051 global_options.holdHandling = H323_HOLD_H450;
03052
03053 for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
03054 if (strcasecmp(cat, "general")) {
03055 utype = ast_variable_retrieve(cfg, cat, "type");
03056 if (utype) {
03057 is_user = is_peer = is_alias = 0;
03058 if (!strcasecmp(utype, "user"))
03059 is_user = 1;
03060 else if (!strcasecmp(utype, "peer"))
03061 is_peer = 1;
03062 else if (!strcasecmp(utype, "friend"))
03063 is_user = is_peer = 1;
03064 else if (!strcasecmp(utype, "h323") || !strcasecmp(utype, "alias"))
03065 is_alias = 1;
03066 else {
03067 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config);
03068 continue;
03069 }
03070 if (is_user) {
03071 user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
03072 if (user) {
03073 ASTOBJ_CONTAINER_LINK(&userl, user);
03074 ASTOBJ_UNREF(user, oh323_destroy_user);
03075 }
03076 }
03077 if (is_peer) {
03078 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
03079 if (peer) {
03080 ASTOBJ_CONTAINER_LINK(&peerl, peer);
03081 ASTOBJ_UNREF(peer, oh323_destroy_peer);
03082 }
03083 }
03084 if (is_alias) {
03085 alias = build_alias(cat, ast_variable_browse(cfg, cat), NULL, 0);
03086 if (alias) {
03087 ASTOBJ_CONTAINER_LINK(&aliasl, alias);
03088 ASTOBJ_UNREF(alias, oh323_destroy_alias);
03089 }
03090 }
03091 } else {
03092 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
03093 }
03094 }
03095 }
03096 ast_config_destroy(cfg);
03097
03098
03099 ASTOBJ_CONTAINER_WRLOCK(&aliasl);
03100 ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
03101 ASTOBJ_RDLOCK(iterator);
03102 if (h323_set_alias(iterator)) {
03103 ast_log(LOG_ERROR, "Alias %s rejected by endpoint\n", alias->name);
03104 ASTOBJ_UNLOCK(iterator);
03105 continue;
03106 }
03107 ASTOBJ_UNLOCK(iterator);
03108 } while (0) );
03109 ASTOBJ_CONTAINER_UNLOCK(&aliasl);
03110
03111
03112 gk_changed = 0;
03113 if (gatekeeper_disable != gk_disable)
03114 gk_changed = is_reload;
03115 else if(!gatekeeper_disable && (gatekeeper_discover != gk_discover))
03116 gk_changed = is_reload;
03117 else if(!gatekeeper_disable && (strncmp(_gatekeeper, gatekeeper, sizeof(_gatekeeper)) != 0))
03118 gk_changed = is_reload;
03119 if (gk_changed) {
03120 if(!gk_disable)
03121 h323_gk_urq();
03122 if (!gatekeeper_disable) {
03123 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03124 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03125 gatekeeper_disable = 1;
03126 }
03127 }
03128 }
03129 return 0;
03130 }
03131
03132 static int h323_reload(void)
03133 {
03134 ast_mutex_lock(&h323_reload_lock);
03135 if (h323_reloading) {
03136 ast_verbose("Previous H.323 reload not yet done\n");
03137 } else {
03138 h323_reloading = 1;
03139 }
03140 ast_mutex_unlock(&h323_reload_lock);
03141 restart_monitor();
03142 return 0;
03143 }
03144
03145 static char *handle_cli_h323_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03146 {
03147 switch (cmd) {
03148 case CLI_INIT:
03149 e->command = "h323 reload";
03150 e->usage =
03151 "Usage: h323 reload\n"
03152 " Reloads H.323 configuration from h323.conf\n";
03153 return NULL;
03154 case CLI_GENERATE:
03155 return NULL;
03156 }
03157
03158 if (a->argc != 2)
03159 return CLI_SHOWUSAGE;
03160
03161 h323_reload();
03162
03163 return CLI_SUCCESS;
03164 }
03165
03166 static int h323_do_reload(void)
03167 {
03168 reload_config(1);
03169 return 0;
03170 }
03171
03172 static int reload(void)
03173 {
03174 if (!sched || !io) {
03175 ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03176 return 0;
03177 }
03178 return h323_reload();
03179 }
03180
03181 static struct ast_cli_entry cli_h323_reload =
03182 AST_CLI_DEFINE(handle_cli_h323_reload, "Reload H.323 configuration");
03183
03184 static enum ast_rtp_glue_result oh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
03185 {
03186 struct oh323_pvt *pvt;
03187 enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
03188
03189 if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
03190 return AST_RTP_GLUE_RESULT_FORBID;
03191
03192 ast_mutex_lock(&pvt->lock);
03193 *instance = pvt->rtp ? ao2_ref(pvt->rtp, +1), pvt->rtp : NULL;
03194 #if 0
03195 if (pvt->options.bridge) {
03196 res = AST_RTP_GLUE_RESULT_REMOTE;
03197 }
03198 #endif
03199 ast_mutex_unlock(&pvt->lock);
03200
03201 return res;
03202 }
03203
03204 static char *convertcap(format_t cap)
03205 {
03206 switch (cap) {
03207 case AST_FORMAT_G723_1:
03208 return "G.723";
03209 case AST_FORMAT_GSM:
03210 return "GSM";
03211 case AST_FORMAT_ULAW:
03212 return "ULAW";
03213 case AST_FORMAT_ALAW:
03214 return "ALAW";
03215 case AST_FORMAT_G722:
03216 return "G.722";
03217 case AST_FORMAT_ADPCM:
03218 return "G.728";
03219 case AST_FORMAT_G729A:
03220 return "G.729";
03221 case AST_FORMAT_SPEEX:
03222 return "SPEEX";
03223 case AST_FORMAT_ILBC:
03224 return "ILBC";
03225 default:
03226 ast_log(LOG_NOTICE, "Don't know how to deal with mode %" PRId64 "\n", cap);
03227 return NULL;
03228 }
03229 }
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 char *mode;
03238
03239 if (!rtp) {
03240 return 0;
03241 }
03242
03243 mode = convertcap(chan->writeformat);
03244 pvt = (struct oh323_pvt *) chan->tech_pvt;
03245 if (!pvt) {
03246 ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
03247 return -1;
03248 }
03249 {
03250 struct ast_sockaddr tmp;
03251
03252 ast_rtp_instance_get_remote_address(rtp, &tmp);
03253 ast_sockaddr_to_sin(&tmp, &them);
03254 ast_rtp_instance_get_local_address(rtp, &tmp);
03255 ast_sockaddr_to_sin(&tmp, &us);
03256 }
03257 #if 0
03258 h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
03259 #endif
03260 return 0;
03261 }
03262
03263 static struct ast_rtp_glue oh323_rtp_glue = {
03264 .type = "H323",
03265 .get_rtp_info = oh323_get_rtp_peer,
03266 .update_peer = oh323_set_rtp_peer,
03267 };
03268
03269 static enum ast_module_load_result load_module(void)
03270 {
03271 int res;
03272
03273 h323debug = 0;
03274 sched = sched_context_create();
03275 if (!sched) {
03276 ast_log(LOG_WARNING, "Unable to create schedule context\n");
03277 return AST_MODULE_LOAD_FAILURE;
03278 }
03279 io = io_context_create();
03280 if (!io) {
03281 ast_log(LOG_WARNING, "Unable to create I/O context\n");
03282 return AST_MODULE_LOAD_FAILURE;
03283 }
03284 ast_cli_register(&cli_h323_reload);
03285 ASTOBJ_CONTAINER_INIT(&userl);
03286 ASTOBJ_CONTAINER_INIT(&peerl);
03287 ASTOBJ_CONTAINER_INIT(&aliasl);
03288 res = reload_config(0);
03289 if (res) {
03290
03291 ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03292 ast_cli_unregister(&cli_h323_reload);
03293 io_context_destroy(io);
03294 io = NULL;
03295 sched_context_destroy(sched);
03296 sched = NULL;
03297 ASTOBJ_CONTAINER_DESTROY(&userl);
03298 ASTOBJ_CONTAINER_DESTROY(&peerl);
03299 ASTOBJ_CONTAINER_DESTROY(&aliasl);
03300 return AST_MODULE_LOAD_DECLINE;
03301 } else {
03302
03303 if (ast_channel_register(&oh323_tech)) {
03304 ast_log(LOG_ERROR, "Unable to register channel class 'H323'\n");
03305 ast_cli_unregister(&cli_h323_reload);
03306 h323_end_process();
03307 io_context_destroy(io);
03308 sched_context_destroy(sched);
03309
03310 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03311 ASTOBJ_CONTAINER_DESTROY(&userl);
03312 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03313 ASTOBJ_CONTAINER_DESTROY(&peerl);
03314 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03315 ASTOBJ_CONTAINER_DESTROY(&aliasl);
03316
03317 return AST_MODULE_LOAD_FAILURE;
03318 }
03319 ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03320
03321 ast_rtp_glue_register(&oh323_rtp_glue);
03322
03323
03324 h323_callback_register(setup_incoming_call,
03325 setup_outgoing_call,
03326 external_rtp_create,
03327 setup_rtp_connection,
03328 cleanup_connection,
03329 chan_ringing,
03330 connection_made,
03331 receive_digit,
03332 answer_call,
03333 progress,
03334 set_dtmf_payload,
03335 hangup_connection,
03336 set_local_capabilities,
03337 set_peer_capabilities,
03338 remote_hold);
03339
03340 if (h323_start_listener(h323_signalling_port, bindaddr)) {
03341 ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
03342 ast_rtp_glue_unregister(&oh323_rtp_glue);
03343 ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03344 ast_cli_unregister(&cli_h323_reload);
03345 h323_end_process();
03346 io_context_destroy(io);
03347 sched_context_destroy(sched);
03348
03349 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03350 ASTOBJ_CONTAINER_DESTROY(&userl);
03351 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03352 ASTOBJ_CONTAINER_DESTROY(&peerl);
03353 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03354 ASTOBJ_CONTAINER_DESTROY(&aliasl);
03355
03356 return AST_MODULE_LOAD_DECLINE;
03357 }
03358
03359 if (!gatekeeper_disable) {
03360 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03361 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03362 gatekeeper_disable = 1;
03363 res = AST_MODULE_LOAD_SUCCESS;
03364 }
03365 }
03366
03367 restart_monitor();
03368 }
03369 return res;
03370 }
03371
03372 static int unload_module(void)
03373 {
03374 struct oh323_pvt *p, *pl;
03375
03376
03377 ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03378 ast_cli_unregister(&cli_h323_reload);
03379
03380 ast_channel_unregister(&oh323_tech);
03381 ast_rtp_glue_unregister(&oh323_rtp_glue);
03382
03383 if (!ast_mutex_lock(&iflock)) {
03384
03385 p = iflist;
03386 while(p) {
03387 if (p->owner) {
03388 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
03389 }
03390 p = p->next;
03391 }
03392 iflist = NULL;
03393 ast_mutex_unlock(&iflock);
03394 } else {
03395 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03396 return -1;
03397 }
03398 if (!ast_mutex_lock(&monlock)) {
03399 if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
03400 if (monitor_thread != pthread_self()) {
03401 pthread_cancel(monitor_thread);
03402 }
03403 pthread_kill(monitor_thread, SIGURG);
03404 pthread_join(monitor_thread, NULL);
03405 }
03406 monitor_thread = AST_PTHREADT_STOP;
03407 ast_mutex_unlock(&monlock);
03408 } else {
03409 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
03410 return -1;
03411 }
03412 if (!ast_mutex_lock(&iflock)) {
03413
03414 p = iflist;
03415 while(p) {
03416 pl = p;
03417 p = p->next;
03418
03419 ast_mutex_destroy(&pl->lock);
03420 ast_free(pl);
03421 }
03422 iflist = NULL;
03423 ast_mutex_unlock(&iflock);
03424 } else {
03425 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03426 return -1;
03427 }
03428 if (!gatekeeper_disable)
03429 h323_gk_urq();
03430 h323_end_process();
03431 if (io)
03432 io_context_destroy(io);
03433 if (sched)
03434 sched_context_destroy(sched);
03435
03436 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03437 ASTOBJ_CONTAINER_DESTROY(&userl);
03438 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03439 ASTOBJ_CONTAINER_DESTROY(&peerl);
03440 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03441 ASTOBJ_CONTAINER_DESTROY(&aliasl);
03442
03443 return 0;
03444 }
03445
03446 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "The NuFone Network's OpenH323 Channel Driver",
03447 .load = load_module,
03448 .unload = unload_module,
03449 .reload = reload,
03450 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
03451 );