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: 328446 $")
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 (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_CONGESTION:
00904 if (c->_state != AST_STATE_UP) {
00905 h323_answering_call(token, 1);
00906 ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
00907 res = 0;
00908 }
00909 break;
00910 case AST_CONTROL_HOLD:
00911 h323_hold_call(token, 1);
00912
00913 ast_moh_start(c, data, NULL);
00914 res = 0;
00915 break;
00916 case AST_CONTROL_UNHOLD:
00917 h323_hold_call(token, 0);
00918 ast_moh_stop(c);
00919 res = 0;
00920 break;
00921 case AST_CONTROL_SRCUPDATE:
00922 ast_rtp_instance_update_source(pvt->rtp);
00923 res = 0;
00924 break;
00925 case AST_CONTROL_SRCCHANGE:
00926 ast_rtp_instance_change_source(pvt->rtp);
00927 res = 0;
00928 break;
00929 case AST_CONTROL_PROCEEDING:
00930 case -1:
00931 break;
00932 default:
00933 ast_log(LOG_WARNING, "OH323: Don't know how to indicate condition %d on %s\n", condition, token);
00934 break;
00935 }
00936
00937 if (h323debug)
00938 ast_debug(1, "OH323: Indicated %d on %s, res=%d\n", condition, token, res);
00939 if (token)
00940 ast_free(token);
00941 oh323_update_info(c);
00942
00943 return res;
00944 }
00945
00946 static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
00947 {
00948 struct oh323_pvt *pvt = (struct oh323_pvt *) newchan->tech_pvt;
00949
00950 ast_mutex_lock(&pvt->lock);
00951 if (pvt->owner != oldchan) {
00952 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, pvt->owner);
00953 return -1;
00954 }
00955 pvt->owner = newchan;
00956 ast_mutex_unlock(&pvt->lock);
00957 return 0;
00958 }
00959
00960 static int __oh323_rtp_create(struct oh323_pvt *pvt)
00961 {
00962 struct ast_sockaddr our_addr;
00963
00964 if (pvt->rtp)
00965 return 0;
00966
00967 {
00968 struct ast_sockaddr tmp;
00969
00970 ast_sockaddr_from_sin(&tmp, &bindaddr);
00971 if (ast_find_ourip(&our_addr, &tmp, AF_INET)) {
00972 ast_mutex_unlock(&pvt->lock);
00973 ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n");
00974 return -1;
00975 }
00976 }
00977 pvt->rtp = ast_rtp_instance_new("asterisk", sched, &our_addr, NULL);
00978 if (!pvt->rtp) {
00979 ast_mutex_unlock(&pvt->lock);
00980 ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
00981 return -1;
00982 }
00983 if (h323debug)
00984 ast_debug(1, "Created RTP channel\n");
00985
00986 ast_rtp_instance_set_qos(pvt->rtp, tos, cos, "H323 RTP");
00987
00988 if (h323debug)
00989 ast_debug(1, "Setting NAT on RTP to %d\n", pvt->options.nat);
00990 ast_rtp_instance_set_prop(pvt->rtp, AST_RTP_PROPERTY_NAT, pvt->options.nat);
00991
00992 if (pvt->dtmf_pt[0] > 0)
00993 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pvt->dtmf_pt[0], "audio", "telephone-event", 0);
00994 if (pvt->dtmf_pt[1] > 0)
00995 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);
00996
00997 if (pvt->peercapability)
00998 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
00999
01000 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01001 ast_jb_configure(pvt->owner, &global_jbconf);
01002 ast_channel_set_fd(pvt->owner, 0, ast_rtp_instance_fd(pvt->rtp, 0));
01003 ast_channel_set_fd(pvt->owner, 1, ast_rtp_instance_fd(pvt->rtp, 1));
01004 ast_queue_frame(pvt->owner, &ast_null_frame);
01005 ast_channel_unlock(pvt->owner);
01006 } else
01007 pvt->update_rtp_info = 1;
01008
01009 return 0;
01010 }
01011
01012
01013 static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const char *host, const char *linkedid)
01014 {
01015 struct ast_channel *ch;
01016 char *cid_num, *cid_name;
01017 int fmt;
01018
01019 if (!ast_strlen_zero(pvt->options.cid_num))
01020 cid_num = pvt->options.cid_num;
01021 else
01022 cid_num = pvt->cd.call_source_e164;
01023
01024 if (!ast_strlen_zero(pvt->options.cid_name))
01025 cid_name = pvt->options.cid_name;
01026 else
01027 cid_name = pvt->cd.call_source_name;
01028
01029
01030 ast_mutex_unlock(&pvt->lock);
01031 ch = ast_channel_alloc(1, state, cid_num, cid_name, pvt->accountcode, pvt->exten, pvt->context, linkedid, pvt->amaflags, "H323/%s", host);
01032
01033 ast_module_ref(ast_module_info->self);
01034 ast_mutex_lock(&pvt->lock);
01035 if (ch) {
01036 ch->tech = &oh323_tech;
01037 if (!(fmt = pvt->jointcapability) && !(fmt = pvt->options.capability))
01038 fmt = global_options.capability;
01039 ch->nativeformats = ast_codec_choose(&pvt->options.prefs, fmt, 1);
01040 pvt->nativeformats = ch->nativeformats;
01041 fmt = ast_best_codec(ch->nativeformats);
01042 ch->writeformat = fmt;
01043 ch->rawwriteformat = fmt;
01044 ch->readformat = fmt;
01045 ch->rawreadformat = fmt;
01046 if (!pvt->rtp)
01047 __oh323_rtp_create(pvt);
01048 #if 0
01049 ast_channel_set_fd(ch, 0, ast_rtp_instance_fd(pvt->rtp, 0));
01050 ast_channel_set_fd(ch, 1, ast_rtp_instance_fd(pvt->rtp, 1));
01051 #endif
01052 #ifdef VIDEO_SUPPORT
01053 if (pvt->vrtp) {
01054 ast_channel_set_fd(ch, 2, ast_rtp_instance_fd(pvt->vrtp, 0));
01055 ast_channel_set_fd(ch, 3, ast_rtp_instance_fd(pvt->vrtp, 1));
01056 }
01057 #endif
01058 #ifdef T38_SUPPORT
01059 if (pvt->udptl) {
01060 ast_channel_set_fd(ch, 4, ast_udptl_fd(pvt->udptl));
01061 }
01062 #endif
01063 if (state == AST_STATE_RING) {
01064 ch->rings = 1;
01065 }
01066
01067 if (pvt->options.dtmfmode & H323_DTMF_INBAND) {
01068 pvt->vad = ast_dsp_new();
01069 ast_dsp_set_features(pvt->vad, DSP_FEATURE_DIGIT_DETECT);
01070 }
01071
01072 ch->tech_pvt = pvt;
01073
01074 pvt->owner = ch;
01075
01076 ast_copy_string(ch->context, pvt->context, sizeof(ch->context));
01077 ast_copy_string(ch->exten, pvt->exten, sizeof(ch->exten));
01078 ch->priority = 1;
01079 if (!ast_strlen_zero(pvt->accountcode)) {
01080 ast_string_field_set(ch, accountcode, pvt->accountcode);
01081 }
01082 if (pvt->amaflags) {
01083 ch->amaflags = pvt->amaflags;
01084 }
01085
01086
01087
01088 if (!ast_strlen_zero(cid_num)) {
01089 ch->caller.ani.number.valid = 1;
01090 ch->caller.ani.number.str = ast_strdup(cid_num);
01091 }
01092
01093 if (pvt->cd.redirect_reason >= 0) {
01094 ch->redirecting.from.number.valid = 1;
01095 ch->redirecting.from.number.str = ast_strdup(pvt->cd.redirect_number);
01096 pbx_builtin_setvar_helper(ch, "PRIREDIRECTREASON", redirectingreason2str(pvt->cd.redirect_reason));
01097 }
01098 ch->caller.id.name.presentation = pvt->cd.presentation;
01099 ch->caller.id.number.presentation = pvt->cd.presentation;
01100 ch->caller.id.number.plan = pvt->cd.type_of_number;
01101
01102 if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) {
01103 ch->dialed.number.str = ast_strdup(pvt->exten);
01104 }
01105 if (pvt->cd.transfer_capability >= 0)
01106 ch->transfercapability = pvt->cd.transfer_capability;
01107 if (state != AST_STATE_DOWN) {
01108 if (ast_pbx_start(ch)) {
01109 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name);
01110 ast_hangup(ch);
01111 ch = NULL;
01112 }
01113 }
01114 } else {
01115 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01116 }
01117 return ch;
01118 }
01119
01120 static struct oh323_pvt *oh323_alloc(int callid)
01121 {
01122 struct oh323_pvt *pvt;
01123
01124 pvt = ast_calloc(1, sizeof(*pvt));
01125 if (!pvt) {
01126 ast_log(LOG_ERROR, "Couldn't allocate private structure. This is bad\n");
01127 return NULL;
01128 }
01129 pvt->cd.redirect_reason = -1;
01130 pvt->cd.transfer_capability = -1;
01131
01132 if (!callid) {
01133 if ((pvt->cd).call_token == NULL) {
01134 (pvt->cd).call_token = ast_calloc(1, 128);
01135 }
01136 if (!pvt->cd.call_token) {
01137 ast_log(LOG_ERROR, "Not enough memory to alocate call token\n");
01138 ast_rtp_instance_destroy(pvt->rtp);
01139 ast_free(pvt);
01140 return NULL;
01141 }
01142 memset((char *)(pvt->cd).call_token, 0, 128);
01143 pvt->cd.call_reference = callid;
01144 }
01145 memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01146 pvt->jointcapability = pvt->options.capability;
01147 if (pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO)) {
01148 pvt->nonCodecCapability |= AST_RTP_DTMF;
01149 } else {
01150 pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01151 }
01152 ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
01153 pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->update_rtp_info = pvt->DTMFsched = -1;
01154 ast_mutex_init(&pvt->lock);
01155
01156 ast_mutex_lock(&iflock);
01157 pvt->next = iflist;
01158 iflist = pvt;
01159 ast_mutex_unlock(&iflock);
01160 return pvt;
01161 }
01162
01163 static struct oh323_pvt *find_call_locked(int call_reference, const char *token)
01164 {
01165 struct oh323_pvt *pvt;
01166
01167 ast_mutex_lock(&iflock);
01168 pvt = iflist;
01169 while(pvt) {
01170 if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) {
01171
01172 if ((token != NULL) && (pvt->cd.call_token != NULL) && (!strcmp(pvt->cd.call_token, token))) {
01173 ast_mutex_lock(&pvt->lock);
01174 ast_mutex_unlock(&iflock);
01175 return pvt;
01176 } else if (token == NULL) {
01177 ast_log(LOG_WARNING, "Call Token is NULL\n");
01178 ast_mutex_lock(&pvt->lock);
01179 ast_mutex_unlock(&iflock);
01180 return pvt;
01181 }
01182 }
01183 pvt = pvt->next;
01184 }
01185 ast_mutex_unlock(&iflock);
01186 return NULL;
01187 }
01188
01189 static int update_state(struct oh323_pvt *pvt, int state, int signal)
01190 {
01191 if (!pvt)
01192 return 0;
01193 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01194 if (state >= 0)
01195 ast_setstate(pvt->owner, state);
01196 if (signal >= 0)
01197 ast_queue_control(pvt->owner, signal);
01198 ast_channel_unlock(pvt->owner);
01199 return 1;
01200 }
01201 else {
01202 if (state >= 0)
01203 pvt->newstate = state;
01204 if (signal >= 0)
01205 pvt->newcontrol = signal;
01206 return 0;
01207 }
01208 }
01209
01210 static struct oh323_alias *build_alias(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
01211 {
01212 struct oh323_alias *alias;
01213 int found = 0;
01214
01215 alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&aliasl, name, name, 0, 0, strcasecmp);
01216
01217 if (alias)
01218 found++;
01219 else {
01220 if (!(alias = ast_calloc(1, sizeof(*alias))))
01221 return NULL;
01222 ASTOBJ_INIT(alias);
01223 }
01224 if (!found && name)
01225 ast_copy_string(alias->name, name, sizeof(alias->name));
01226 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01227 if (!strcasecmp(v->name, "e164")) {
01228 ast_copy_string(alias->e164, v->value, sizeof(alias->e164));
01229 } else if (!strcasecmp(v->name, "prefix")) {
01230 ast_copy_string(alias->prefix, v->value, sizeof(alias->prefix));
01231 } else if (!strcasecmp(v->name, "context")) {
01232 ast_copy_string(alias->context, v->value, sizeof(alias->context));
01233 } else if (!strcasecmp(v->name, "secret")) {
01234 ast_copy_string(alias->secret, v->value, sizeof(alias->secret));
01235 } else {
01236 if (strcasecmp(v->value, "h323")) {
01237 ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->name);
01238 }
01239 }
01240 }
01241 ASTOBJ_UNMARK(alias);
01242 return alias;
01243 }
01244
01245 static struct oh323_alias *realtime_alias(const char *alias)
01246 {
01247 struct ast_variable *var, *tmp;
01248 struct oh323_alias *a;
01249
01250 var = ast_load_realtime("h323", "name", alias, SENTINEL);
01251
01252 if (!var)
01253 return NULL;
01254
01255 for (tmp = var; tmp; tmp = tmp->next) {
01256 if (!strcasecmp(tmp->name, "type") &&
01257 !(!strcasecmp(tmp->value, "alias") || !strcasecmp(tmp->value, "h323"))) {
01258 ast_variables_destroy(var);
01259 return NULL;
01260 }
01261 }
01262
01263 a = build_alias(alias, var, NULL, 1);
01264
01265 ast_variables_destroy(var);
01266
01267 return a;
01268 }
01269
01270 static int update_common_options(struct ast_variable *v, struct call_options *options)
01271 {
01272 int tmp = 0;
01273 char *val, *opt;
01274
01275 if (!strcasecmp(v->name, "allow")) {
01276 ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 1);
01277 } else if (!strcasecmp(v->name, "autoframing")) {
01278 options->autoframing = ast_true(v->value);
01279 } else if (!strcasecmp(v->name, "disallow")) {
01280 ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0);
01281 } else if (!strcasecmp(v->name, "dtmfmode")) {
01282 val = ast_strdupa(v->value);
01283 if ((opt = strchr(val, ':')) != (char *)NULL) {
01284 *opt++ = '\0';
01285 tmp = atoi(opt);
01286 }
01287 if (!strcasecmp(v->value, "inband")) {
01288 options->dtmfmode |= H323_DTMF_INBAND;
01289 } else if (!strcasecmp(val, "rfc2833")) {
01290 options->dtmfmode |= H323_DTMF_RFC2833;
01291 if (!opt) {
01292 options->dtmfcodec[0] = H323_DTMF_RFC2833_PT;
01293 } else if ((tmp >= 96) && (tmp < 128)) {
01294 options->dtmfcodec[0] = tmp;
01295 } else {
01296 options->dtmfcodec[0] = H323_DTMF_RFC2833_PT;
01297 ast_log(LOG_WARNING, "Unknown rfc2833 payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[0]);
01298 }
01299 } else if (!strcasecmp(val, "cisco")) {
01300 options->dtmfmode |= H323_DTMF_CISCO;
01301 if (!opt) {
01302 options->dtmfcodec[1] = H323_DTMF_CISCO_PT;
01303 } else if ((tmp >= 96) && (tmp < 128)) {
01304 options->dtmfcodec[1] = tmp;
01305 } else {
01306 options->dtmfcodec[1] = H323_DTMF_CISCO_PT;
01307 ast_log(LOG_WARNING, "Unknown Cisco DTMF payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[1]);
01308 }
01309 } else if (!strcasecmp(v->value, "h245-signal")) {
01310 options->dtmfmode |= H323_DTMF_SIGNAL;
01311 } else {
01312 ast_log(LOG_WARNING, "Unknown dtmf mode '%s' at line %d\n", v->value, v->lineno);
01313 }
01314 } else if (!strcasecmp(v->name, "dtmfcodec")) {
01315 ast_log(LOG_NOTICE, "Option %s at line %d is deprecated. Use dtmfmode=rfc2833[:<payload>] instead.\n", v->name, v->lineno);
01316 tmp = atoi(v->value);
01317 if (tmp < 96)
01318 ast_log(LOG_WARNING, "Invalid %s value %s at line %d\n", v->name, v->value, v->lineno);
01319 else
01320 options->dtmfcodec[0] = tmp;
01321 } else if (!strcasecmp(v->name, "bridge")) {
01322 options->bridge = ast_true(v->value);
01323 } else if (!strcasecmp(v->name, "nat")) {
01324 options->nat = ast_true(v->value);
01325 } else if (!strcasecmp(v->name, "fastStart")) {
01326 options->fastStart = ast_true(v->value);
01327 } else if (!strcasecmp(v->name, "h245Tunneling")) {
01328 options->h245Tunneling = ast_true(v->value);
01329 } else if (!strcasecmp(v->name, "silenceSuppression")) {
01330 options->silenceSuppression = ast_true(v->value);
01331 } else if (!strcasecmp(v->name, "progress_setup")) {
01332 tmp = atoi(v->value);
01333 if ((tmp != 0) && (tmp != 1) && (tmp != 3) && (tmp != 8)) {
01334 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
01335 tmp = 0;
01336 }
01337 options->progress_setup = tmp;
01338 } else if (!strcasecmp(v->name, "progress_alert")) {
01339 tmp = atoi(v->value);
01340 if ((tmp != 0) && (tmp != 1) && (tmp != 8)) {
01341 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
01342 tmp = 0;
01343 }
01344 options->progress_alert = tmp;
01345 } else if (!strcasecmp(v->name, "progress_audio")) {
01346 options->progress_audio = ast_true(v->value);
01347 } else if (!strcasecmp(v->name, "callerid")) {
01348 ast_callerid_split(v->value, options->cid_name, sizeof(options->cid_name), options->cid_num, sizeof(options->cid_num));
01349 } else if (!strcasecmp(v->name, "fullname")) {
01350 ast_copy_string(options->cid_name, v->value, sizeof(options->cid_name));
01351 } else if (!strcasecmp(v->name, "cid_number")) {
01352 ast_copy_string(options->cid_num, v->value, sizeof(options->cid_num));
01353 } else if (!strcasecmp(v->name, "tunneling")) {
01354 if (!strcasecmp(v->value, "none"))
01355 options->tunnelOptions = 0;
01356 else if (!strcasecmp(v->value, "cisco"))
01357 options->tunnelOptions |= H323_TUNNEL_CISCO;
01358 else if (!strcasecmp(v->value, "qsig"))
01359 options->tunnelOptions |= H323_TUNNEL_QSIG;
01360 else
01361 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
01362 } else if (!strcasecmp(v->name, "hold")) {
01363 if (!strcasecmp(v->value, "none"))
01364 options->holdHandling = ~0;
01365 else if (!strcasecmp(v->value, "notify"))
01366 options->holdHandling |= H323_HOLD_NOTIFY;
01367 else if (!strcasecmp(v->value, "q931only"))
01368 options->holdHandling |= H323_HOLD_NOTIFY | H323_HOLD_Q931ONLY;
01369 else if (!strcasecmp(v->value, "h450"))
01370 options->holdHandling |= H323_HOLD_H450;
01371 else
01372 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
01373 } else
01374 return 1;
01375
01376 return 0;
01377 }
01378
01379 static struct oh323_user *build_user(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
01380 {
01381 struct oh323_user *user;
01382 struct ast_ha *oldha;
01383 int found = 0;
01384 int format;
01385
01386 user = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&userl, name, name, 0, 0, strcmp);
01387
01388 if (user)
01389 found++;
01390 else {
01391 if (!(user = ast_calloc(1, sizeof(*user))))
01392 return NULL;
01393 ASTOBJ_INIT(user);
01394 }
01395 oldha = user->ha;
01396 user->ha = (struct ast_ha *)NULL;
01397 memcpy(&user->options, &global_options, sizeof(user->options));
01398 user->options.dtmfmode = 0;
01399 user->options.holdHandling = 0;
01400
01401 ast_copy_string(user->context, default_context, sizeof(user->context));
01402 if (user && !found)
01403 ast_copy_string(user->name, name, sizeof(user->name));
01404
01405 #if 0
01406 if (user->chanvars) {
01407 ast_variables_destroy(user->chanvars);
01408 user->chanvars = NULL;
01409 }
01410 #endif
01411
01412 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01413 if (!update_common_options(v, &user->options))
01414 continue;
01415 if (!strcasecmp(v->name, "context")) {
01416 ast_copy_string(user->context, v->value, sizeof(user->context));
01417 } else if (!strcasecmp(v->name, "secret")) {
01418 ast_copy_string(user->secret, v->value, sizeof(user->secret));
01419 } else if (!strcasecmp(v->name, "accountcode")) {
01420 ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
01421 } else if (!strcasecmp(v->name, "host")) {
01422 if (!strcasecmp(v->value, "dynamic")) {
01423 ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n");
01424 ASTOBJ_UNREF(user, oh323_destroy_user);
01425 return NULL;
01426 } else {
01427 struct ast_sockaddr tmp;
01428
01429 if (ast_get_ip(&tmp, v->value)) {
01430 ASTOBJ_UNREF(user, oh323_destroy_user);
01431 return NULL;
01432 }
01433 ast_sockaddr_to_sin(&tmp, &user->addr);
01434 }
01435
01436 user->host = 1;
01437 } else if (!strcasecmp(v->name, "amaflags")) {
01438 format = ast_cdr_amaflags2int(v->value);
01439 if (format < 0) {
01440 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
01441 } else {
01442 user->amaflags = format;
01443 }
01444 } else if (!strcasecmp(v->name, "permit") ||
01445 !strcasecmp(v->name, "deny")) {
01446 int ha_error = 0;
01447
01448 user->ha = ast_append_ha(v->name, v->value, user->ha, &ha_error);
01449 if (ha_error)
01450 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
01451 }
01452 }
01453 if (!user->options.dtmfmode)
01454 user->options.dtmfmode = global_options.dtmfmode;
01455 if (user->options.holdHandling == ~0)
01456 user->options.holdHandling = 0;
01457 else if (!user->options.holdHandling)
01458 user->options.holdHandling = global_options.holdHandling;
01459 ASTOBJ_UNMARK(user);
01460 ast_free_ha(oldha);
01461 return user;
01462 }
01463
01464 static struct oh323_user *realtime_user(const call_details_t *cd)
01465 {
01466 struct ast_variable *var, *tmp;
01467 struct oh323_user *user;
01468 const char *username;
01469
01470 if (userbyalias)
01471 var = ast_load_realtime("h323", "name", username = cd->call_source_aliases, SENTINEL);
01472 else {
01473 username = (char *)NULL;
01474 var = ast_load_realtime("h323", "host", cd->sourceIp, SENTINEL);
01475 }
01476
01477 if (!var)
01478 return NULL;
01479
01480 for (tmp = var; tmp; tmp = tmp->next) {
01481 if (!strcasecmp(tmp->name, "type") &&
01482 !(!strcasecmp(tmp->value, "user") || !strcasecmp(tmp->value, "friend"))) {
01483 ast_variables_destroy(var);
01484 return NULL;
01485 } else if (!username && !strcasecmp(tmp->name, "name"))
01486 username = tmp->value;
01487 }
01488
01489 if (!username) {
01490 ast_log(LOG_WARNING, "Cannot determine user name for IP address %s\n", cd->sourceIp);
01491 ast_variables_destroy(var);
01492 return NULL;
01493 }
01494
01495 user = build_user(username, var, NULL, 1);
01496
01497 ast_variables_destroy(var);
01498
01499 return user;
01500 }
01501
01502 static struct oh323_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
01503 {
01504 struct oh323_peer *peer;
01505 struct ast_ha *oldha;
01506 int found = 0;
01507
01508 peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp);
01509
01510 if (peer)
01511 found++;
01512 else {
01513 if (!(peer = ast_calloc(1, sizeof(*peer))))
01514 return NULL;
01515 ASTOBJ_INIT(peer);
01516 }
01517 oldha = peer->ha;
01518 peer->ha = NULL;
01519 memcpy(&peer->options, &global_options, sizeof(peer->options));
01520 peer->options.dtmfmode = 0;
01521 peer->options.holdHandling = 0;
01522 peer->addr.sin_port = htons(h323_signalling_port);
01523 peer->addr.sin_family = AF_INET;
01524 if (!found && name)
01525 ast_copy_string(peer->name, name, sizeof(peer->name));
01526
01527 #if 0
01528 if (peer->chanvars) {
01529 ast_variables_destroy(peer->chanvars);
01530 peer->chanvars = NULL;
01531 }
01532 #endif
01533
01534 peer->mailbox[0] = '\0';
01535
01536 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01537 if (!update_common_options(v, &peer->options))
01538 continue;
01539 if (!strcasecmp(v->name, "host")) {
01540 if (!strcasecmp(v->value, "dynamic")) {
01541 ast_log(LOG_ERROR, "Dynamic host configuration not implemented.\n");
01542 ASTOBJ_UNREF(peer, oh323_destroy_peer);
01543 return NULL;
01544 }
01545 {
01546 struct ast_sockaddr tmp;
01547
01548 if (ast_get_ip(&tmp, v->value)) {
01549 ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value);
01550 ASTOBJ_UNREF(peer, oh323_destroy_peer);
01551 return NULL;
01552 }
01553 ast_sockaddr_to_sin(&tmp, &peer->addr);
01554 }
01555 } else if (!strcasecmp(v->name, "port")) {
01556 peer->addr.sin_port = htons(atoi(v->value));
01557 } else if (!strcasecmp(v->name, "permit") ||
01558 !strcasecmp(v->name, "deny")) {
01559 int ha_error = 0;
01560
01561 peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error);
01562 if (ha_error)
01563 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
01564 } else if (!strcasecmp(v->name, "mailbox")) {
01565 ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox));
01566 } else if (!strcasecmp(v->name, "hasvoicemail")) {
01567 if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) {
01568 ast_copy_string(peer->mailbox, name, sizeof(peer->mailbox));
01569 }
01570 }
01571 }
01572 if (!peer->options.dtmfmode)
01573 peer->options.dtmfmode = global_options.dtmfmode;
01574 if (peer->options.holdHandling == ~0)
01575 peer->options.holdHandling = 0;
01576 else if (!peer->options.holdHandling)
01577 peer->options.holdHandling = global_options.holdHandling;
01578 ASTOBJ_UNMARK(peer);
01579 ast_free_ha(oldha);
01580 return peer;
01581 }
01582
01583 static struct oh323_peer *realtime_peer(const char *peername, struct sockaddr_in *sin)
01584 {
01585 struct oh323_peer *peer;
01586 struct ast_variable *var;
01587 struct ast_variable *tmp;
01588 const char *addr = NULL;
01589
01590
01591 if (peername)
01592 var = ast_load_realtime("h323", "name", peername, SENTINEL);
01593 else if (sin)
01594 var = ast_load_realtime("h323", "host", addr = ast_inet_ntoa(sin->sin_addr), SENTINEL);
01595 else
01596 return NULL;
01597
01598 if (!var)
01599 return NULL;
01600
01601 for (tmp = var; tmp; tmp = tmp->next) {
01602
01603 if (!strcasecmp(tmp->name, "type") &&
01604 !(!strcasecmp(tmp->value, "peer") || !strcasecmp(tmp->value, "friend"))) {
01605 ast_variables_destroy(var);
01606 return NULL;
01607 } else if (!peername && !strcasecmp(tmp->name, "name")) {
01608 peername = tmp->value;
01609 }
01610 }
01611
01612 if (!peername) {
01613 ast_log(LOG_WARNING, "Cannot determine peer name for IP address %s\n", addr);
01614 ast_variables_destroy(var);
01615 return NULL;
01616 }
01617
01618
01619 peer = build_peer(peername, var, NULL, 1);
01620
01621 ast_variables_destroy(var);
01622
01623 return peer;
01624 }
01625
01626 static int oh323_addrcmp_str(struct in_addr inaddr, char *addr)
01627 {
01628 return strcmp(ast_inet_ntoa(inaddr), addr);
01629 }
01630
01631 static struct oh323_user *find_user(const call_details_t *cd, int realtime)
01632 {
01633 struct oh323_user *u;
01634
01635 if (userbyalias)
01636 u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases);
01637 else
01638 u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str);
01639
01640 if (!u && realtime)
01641 u = realtime_user(cd);
01642
01643 if (!u && h323debug)
01644 ast_debug(1, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp);
01645
01646 return u;
01647 }
01648
01649 static int oh323_addrcmp(struct sockaddr_in addr, struct sockaddr_in *sin)
01650 {
01651 int res;
01652
01653 if (!sin)
01654 res = -1;
01655 else
01656 res = inaddrcmp(&addr , sin);
01657
01658 return res;
01659 }
01660
01661 static struct oh323_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime)
01662 {
01663 struct oh323_peer *p;
01664
01665 if (peer)
01666 p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
01667 else
01668 p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
01669
01670 if (!p && realtime)
01671 p = realtime_peer(peer, sin);
01672
01673 if (!p && h323debug)
01674 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>"));
01675
01676 return p;
01677 }
01678
01679 static int create_addr(struct oh323_pvt *pvt, char *opeer)
01680 {
01681 struct hostent *hp;
01682 struct ast_hostent ahp;
01683 struct oh323_peer *p;
01684 int portno;
01685 int found = 0;
01686 char *port;
01687 char *hostn;
01688 char peer[256] = "";
01689
01690 ast_copy_string(peer, opeer, sizeof(peer));
01691 port = strchr(peer, ':');
01692 if (port) {
01693 *port = '\0';
01694 port++;
01695 }
01696 pvt->sa.sin_family = AF_INET;
01697 p = find_peer(peer, NULL, 1);
01698 if (p) {
01699 found++;
01700 memcpy(&pvt->options, &p->options, sizeof(pvt->options));
01701 pvt->jointcapability = pvt->options.capability;
01702 if (pvt->options.dtmfmode) {
01703 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01704 pvt->nonCodecCapability |= AST_RTP_DTMF;
01705 } else {
01706 pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01707 }
01708 }
01709 if (p->addr.sin_addr.s_addr) {
01710 pvt->sa.sin_addr = p->addr.sin_addr;
01711 pvt->sa.sin_port = p->addr.sin_port;
01712 }
01713 ASTOBJ_UNREF(p, oh323_destroy_peer);
01714 }
01715 if (!p && !found) {
01716 hostn = peer;
01717 if (port) {
01718 portno = atoi(port);
01719 } else {
01720 portno = h323_signalling_port;
01721 }
01722 hp = ast_gethostbyname(hostn, &ahp);
01723 if (hp) {
01724 memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
01725 pvt->sa.sin_port = htons(portno);
01726
01727 p = find_peer(NULL, &pvt->sa, 1);
01728 memcpy(&pvt->options, (p ? &p->options : &global_options), sizeof(pvt->options));
01729 pvt->jointcapability = pvt->options.capability;
01730 if (p) {
01731 ASTOBJ_UNREF(p, oh323_destroy_peer);
01732 }
01733 if (pvt->options.dtmfmode) {
01734 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01735 pvt->nonCodecCapability |= AST_RTP_DTMF;
01736 } else {
01737 pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01738 }
01739 }
01740 return 0;
01741 } else {
01742 ast_log(LOG_WARNING, "No such host: %s\n", peer);
01743 return -1;
01744 }
01745 } else if (!found) {
01746 return -1;
01747 } else {
01748 return 0;
01749 }
01750 }
01751 static struct ast_channel *oh323_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
01752 {
01753 format_t oldformat;
01754 struct oh323_pvt *pvt;
01755 struct ast_channel *tmpc = NULL;
01756 char *dest = (char *)data;
01757 char *ext, *host;
01758 char *h323id = NULL;
01759 char tmp[256], tmp1[256];
01760
01761 if (h323debug)
01762 ast_debug(1, "type=%s, format=%s, data=%s.\n", type, ast_getformatname_multiple(tmp, sizeof(tmp), format), (char *)data);
01763
01764 pvt = oh323_alloc(0);
01765 if (!pvt) {
01766 ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data);
01767 return NULL;
01768 }
01769 oldformat = format;
01770 format &= AST_FORMAT_AUDIO_MASK;
01771 if (!format) {
01772 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), format));
01773 oh323_destroy(pvt);
01774 if (cause)
01775 *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
01776 return NULL;
01777 }
01778 ast_copy_string(tmp, dest, sizeof(tmp));
01779 host = strchr(tmp, '@');
01780 if (host) {
01781 *host = '\0';
01782 host++;
01783 ext = tmp;
01784 } else {
01785 ext = strrchr(tmp, '/');
01786 if (ext)
01787 *ext++ = '\0';
01788 host = tmp;
01789 }
01790 strtok_r(host, "/", &(h323id));
01791 if (!ast_strlen_zero(h323id)) {
01792 h323_set_id(h323id);
01793 }
01794 if (ext) {
01795 ast_copy_string(pvt->exten, ext, sizeof(pvt->exten));
01796 }
01797 if (h323debug)
01798 ast_debug(1, "Extension: %s Host: %s\n", pvt->exten, host);
01799
01800 if (gatekeeper_disable) {
01801 if (create_addr(pvt, host)) {
01802 oh323_destroy(pvt);
01803 if (cause)
01804 *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01805 return NULL;
01806 }
01807 }
01808 else {
01809 memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01810 pvt->jointcapability = pvt->options.capability;
01811 if (pvt->options.dtmfmode) {
01812 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01813 pvt->nonCodecCapability |= AST_RTP_DTMF;
01814 } else {
01815 pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01816 }
01817 }
01818 }
01819
01820 ast_mutex_lock(&caplock);
01821
01822 snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
01823 tmp1[sizeof(tmp1)-1] = '\0';
01824 ast_mutex_unlock(&caplock);
01825
01826 ast_mutex_lock(&pvt->lock);
01827 tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1, requestor ? requestor->linkedid : NULL);
01828 ast_mutex_unlock(&pvt->lock);
01829 if (!tmpc) {
01830 oh323_destroy(pvt);
01831 if (cause)
01832 *cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
01833 }
01834 ast_update_use_count();
01835 restart_monitor();
01836 return tmpc;
01837 }
01838
01839
01840 static struct oh323_alias *find_alias(const char *source_aliases, int realtime)
01841 {
01842 struct oh323_alias *a;
01843
01844 a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
01845
01846 if (!a && realtime)
01847 a = realtime_alias(source_aliases);
01848
01849 return a;
01850 }
01851
01852
01853
01854
01855
01856 static int receive_digit(unsigned call_reference, char digit, const char *token, int duration)
01857 {
01858 struct oh323_pvt *pvt;
01859 int res;
01860
01861 pvt = find_call_locked(call_reference, token);
01862 if (!pvt) {
01863 ast_log(LOG_ERROR, "Received digit '%c' (%u ms) for call %s without private structure\n", digit, duration, token);
01864 return -1;
01865 }
01866 if (h323debug)
01867 ast_log(LOG_DTMF, "Received %s digit '%c' (%u ms) for call %s\n", (digit == ' ' ? "update for" : "new"), (digit == ' ' ? pvt->curDTMF : digit), duration, token);
01868
01869 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01870 if (digit == '!')
01871 res = ast_queue_control(pvt->owner, AST_CONTROL_FLASH);
01872 else {
01873 struct ast_frame f = {
01874 .frametype = AST_FRAME_DTMF_END,
01875 .subclass.integer = digit,
01876 .samples = duration * 8,
01877 .len = duration,
01878 .src = "SEND_DIGIT",
01879 };
01880 if (digit == ' ') {
01881 f.subclass.integer = pvt->curDTMF;
01882 AST_SCHED_DEL(sched, pvt->DTMFsched);
01883 } else {
01884 if (pvt->DTMFsched >= 0) {
01885
01886 AST_SCHED_DEL(sched, pvt->DTMFsched);
01887 f.subclass.integer = pvt->curDTMF;
01888 f.samples = f.len = 0;
01889 ast_queue_frame(pvt->owner, &f);
01890
01891 f.subclass.integer = digit;
01892 f.samples = duration * 8;
01893 f.len = duration;
01894 }
01895 if (duration) {
01896 f.frametype = AST_FRAME_DTMF_BEGIN;
01897 pvt->DTMFsched = ast_sched_add(sched, duration, oh323_simulate_dtmf_end, pvt);
01898 if (h323debug)
01899 ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", duration, pvt->DTMFsched);
01900 }
01901 pvt->curDTMF = digit;
01902 }
01903 res = ast_queue_frame(pvt->owner, &f);
01904 }
01905 ast_channel_unlock(pvt->owner);
01906 } else {
01907 if (digit == '!')
01908 pvt->newcontrol = AST_CONTROL_FLASH;
01909 else {
01910 pvt->newduration = duration;
01911 pvt->newdigit = digit;
01912 }
01913 res = 0;
01914 }
01915 ast_mutex_unlock(&pvt->lock);
01916 return res;
01917 }
01918
01919
01920
01921
01922
01923
01924 static struct rtp_info *external_rtp_create(unsigned call_reference, const char * token)
01925 {
01926 struct oh323_pvt *pvt;
01927 struct sockaddr_in us;
01928 struct rtp_info *info;
01929
01930 info = ast_calloc(1, sizeof(*info));
01931 if (!info) {
01932 ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
01933 return NULL;
01934 }
01935 pvt = find_call_locked(call_reference, token);
01936 if (!pvt) {
01937 ast_free(info);
01938 ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
01939 return NULL;
01940 }
01941 if (!pvt->rtp)
01942 __oh323_rtp_create(pvt);
01943 if (!pvt->rtp) {
01944 ast_mutex_unlock(&pvt->lock);
01945 ast_free(info);
01946 ast_log(LOG_ERROR, "No RTP stream is available for call %s (%d)", token, call_reference);
01947 return NULL;
01948 }
01949
01950 {
01951 struct ast_sockaddr tmp;
01952
01953 ast_rtp_instance_get_local_address(pvt->rtp, &tmp);
01954 ast_sockaddr_to_sin(&tmp, &us);
01955 }
01956 ast_mutex_unlock(&pvt->lock);
01957
01958 ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
01959 info->port = ntohs(us.sin_port);
01960 if (h323debug)
01961 ast_debug(1, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
01962 return info;
01963 }
01964
01965
01966
01967
01968
01969
01970 static void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt)
01971 {
01972 struct oh323_pvt *pvt;
01973 struct sockaddr_in them;
01974 int nativeformats_changed;
01975 enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE;
01976
01977 if (h323debug)
01978 ast_debug(1, "Setting up RTP connection for %s\n", token);
01979
01980
01981 pvt = find_call_locked(call_reference, token);
01982 if (!pvt) {
01983 ast_log(LOG_ERROR, "Something is wrong: rtp\n");
01984 return;
01985 }
01986 if (pvt->alreadygone) {
01987 ast_mutex_unlock(&pvt->lock);
01988 return;
01989 }
01990
01991 if (!pvt->rtp)
01992 __oh323_rtp_create(pvt);
01993
01994 if ((pt == 2) && (pvt->jointcapability & AST_FORMAT_G726_AAL2)) {
01995 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);
01996 }
01997
01998 them.sin_family = AF_INET;
01999
02000 them.sin_addr.s_addr = inet_addr(remoteIp);
02001 them.sin_port = htons(remotePort);
02002
02003 if (them.sin_addr.s_addr) {
02004 {
02005 struct ast_sockaddr tmp;
02006
02007 ast_sockaddr_from_sin(&tmp, &them);
02008 ast_rtp_instance_set_remote_address(pvt->rtp, &tmp);
02009 }
02010 if (pvt->recvonly) {
02011 pvt->recvonly = 0;
02012 rtp_change = NEED_UNHOLD;
02013 }
02014 } else {
02015 ast_rtp_instance_stop(pvt->rtp);
02016 if (!pvt->recvonly) {
02017 pvt->recvonly = 1;
02018 rtp_change = NEED_HOLD;
02019 }
02020 }
02021
02022
02023 nativeformats_changed = 0;
02024 if (pt != 128 && pvt->rtp) {
02025 struct ast_rtp_payload_type rtptype = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(pvt->rtp), pt);
02026 if (h323debug)
02027 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);
02028 if (pvt->nativeformats != rtptype.code) {
02029 pvt->nativeformats = rtptype.code;
02030 nativeformats_changed = 1;
02031 }
02032 } else if (h323debug)
02033 ast_log(LOG_NOTICE, "Payload type is unknown, formats isn't changed\n");
02034
02035
02036 if (nativeformats_changed || pvt->options.progress_audio || (rtp_change != NEED_NONE)) {
02037 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02038
02039 if (pvt->owner->nativeformats != pvt->nativeformats) {
02040 if (h323debug) {
02041 char tmp[256], tmp2[256];
02042 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));
02043 }
02044 pvt->owner->nativeformats = pvt->nativeformats;
02045 ast_set_read_format(pvt->owner, pvt->owner->readformat);
02046 ast_set_write_format(pvt->owner, pvt->owner->writeformat);
02047 }
02048 if (pvt->options.progress_audio)
02049 ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);
02050 switch (rtp_change) {
02051 case NEED_HOLD:
02052 ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02053 break;
02054 case NEED_UNHOLD:
02055 ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02056 break;
02057 default:
02058 break;
02059 }
02060 ast_channel_unlock(pvt->owner);
02061 }
02062 else {
02063 if (pvt->options.progress_audio)
02064 pvt->newcontrol = AST_CONTROL_PROGRESS;
02065 else if (rtp_change == NEED_HOLD)
02066 pvt->newcontrol = AST_CONTROL_HOLD;
02067 else if (rtp_change == NEED_UNHOLD)
02068 pvt->newcontrol = AST_CONTROL_UNHOLD;
02069 if (h323debug)
02070 ast_debug(1, "RTP connection preparation for %s is pending...\n", token);
02071 }
02072 }
02073 ast_mutex_unlock(&pvt->lock);
02074
02075 if (h323debug)
02076 ast_debug(1, "RTP connection prepared for %s\n", token);
02077
02078 return;
02079 }
02080
02081
02082
02083
02084
02085 static void connection_made(unsigned call_reference, const char *token)
02086 {
02087 struct oh323_pvt *pvt;
02088
02089 if (h323debug)
02090 ast_debug(1, "Call %s answered\n", token);
02091
02092 pvt = find_call_locked(call_reference, token);
02093 if (!pvt) {
02094 ast_log(LOG_ERROR, "Something is wrong: connection\n");
02095 return;
02096 }
02097
02098
02099 if (!pvt->outgoing) {
02100 ast_mutex_unlock(&pvt->lock);
02101 return;
02102 }
02103
02104 if (!pvt->connection_established) {
02105 pvt->connection_established = 1;
02106 update_state(pvt, -1, AST_CONTROL_ANSWER);
02107 }
02108 ast_mutex_unlock(&pvt->lock);
02109 return;
02110 }
02111
02112 static int progress(unsigned call_reference, const char *token, int inband)
02113 {
02114 struct oh323_pvt *pvt;
02115
02116 if (h323debug)
02117 ast_debug(1, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
02118
02119 pvt = find_call_locked(call_reference, token);
02120 if (!pvt) {
02121 ast_log(LOG_ERROR, "Private structure not found in progress.\n");
02122 return -1;
02123 }
02124 if (!pvt->owner) {
02125 ast_mutex_unlock(&pvt->lock);
02126 ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");
02127 return -1;
02128 }
02129 update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));
02130 ast_mutex_unlock(&pvt->lock);
02131
02132 return 0;
02133 }
02134
02135
02136
02137
02138
02139
02140 static call_options_t *setup_incoming_call(call_details_t *cd)
02141 {
02142 struct oh323_pvt *pvt;
02143 struct oh323_user *user = NULL;
02144 struct oh323_alias *alias = NULL;
02145
02146 if (h323debug)
02147 ast_debug(1, "Setting up incoming call for %s\n", cd->call_token);
02148
02149
02150 pvt = oh323_alloc(cd->call_reference);
02151
02152 if (!pvt) {
02153 ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
02154 cleanup_call_details(cd);
02155 return NULL;
02156 }
02157
02158
02159 memcpy(&pvt->cd, cd, sizeof(pvt->cd));
02160 memcpy(&pvt->options, &global_options, sizeof(pvt->options));
02161 pvt->jointcapability = pvt->options.capability;
02162
02163 if (h323debug) {
02164 ast_verb(3, "Setting up Call\n");
02165 ast_verb(3, " \tCall token: [%s]\n", pvt->cd.call_token);
02166 ast_verb(3, " \tCalling party name: [%s]\n", pvt->cd.call_source_name);
02167 ast_verb(3, " \tCalling party number: [%s]\n", pvt->cd.call_source_e164);
02168 ast_verb(3, " \tCalled party name: [%s]\n", pvt->cd.call_dest_alias);
02169 ast_verb(3, " \tCalled party number: [%s]\n", pvt->cd.call_dest_e164);
02170 if (pvt->cd.redirect_reason >= 0)
02171 ast_verb(3, " \tRedirecting party number: [%s] (reason %d)\n", pvt->cd.redirect_number, pvt->cd.redirect_reason);
02172 ast_verb(3, " \tCalling party IP: [%s]\n", pvt->cd.sourceIp);
02173 }
02174
02175
02176 if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && !gatekeeper_disable) {
02177 if (!ast_strlen_zero(cd->call_dest_e164)) {
02178 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02179 ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02180 } else {
02181 alias = find_alias(cd->call_dest_alias, 1);
02182 if (!alias) {
02183 ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias);
02184 oh323_destroy(pvt);
02185 return NULL;
02186 }
02187 ast_copy_string(pvt->exten, alias->name, sizeof(pvt->exten));
02188 ast_copy_string(pvt->context, alias->context, sizeof(pvt->context));
02189 }
02190 } else {
02191
02192
02193 user = find_user(cd, 1);
02194 if (!user) {
02195 if (!acceptAnonymous) {
02196 ast_log(LOG_NOTICE, "Anonymous call from '%s@%s' rejected\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02197 oh323_destroy(pvt);
02198 return NULL;
02199 }
02200 if (ast_strlen_zero(default_context)) {
02201 ast_log(LOG_ERROR, "Call from '%s@%s' rejected due to no default context\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02202 oh323_destroy(pvt);
02203 return NULL;
02204 }
02205 ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02206 if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02207 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02208 } else {
02209 ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02210 }
02211 if (h323debug)
02212 ast_debug(1, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten);
02213 } else {
02214 if (user->host) {
02215 if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) {
02216 if (ast_strlen_zero(user->context)) {
02217 if (ast_strlen_zero(default_context)) {
02218 ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp);
02219 oh323_destroy(pvt);
02220 ASTOBJ_UNREF(user, oh323_destroy_user);
02221 return NULL;
02222 }
02223 ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02224 } else {
02225 ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02226 }
02227 pvt->exten[0] = 'i';
02228 pvt->exten[1] = '\0';
02229 ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp);
02230 oh323_destroy(pvt);
02231 ASTOBJ_UNREF(user, oh323_destroy_user);
02232 return NULL;
02233 }
02234 }
02235 ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02236 memcpy(&pvt->options, &user->options, sizeof(pvt->options));
02237 pvt->jointcapability = pvt->options.capability;
02238 if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02239 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02240 } else {
02241 ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02242 }
02243 if (!ast_strlen_zero(user->accountcode)) {
02244 ast_copy_string(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode));
02245 }
02246 if (user->amaflags) {
02247 pvt->amaflags = user->amaflags;
02248 }
02249 ASTOBJ_UNREF(user, oh323_destroy_user);
02250 }
02251 }
02252 return &pvt->options;
02253 }
02254
02255
02256
02257
02258
02259
02260 static int answer_call(unsigned call_reference, const char *token)
02261 {
02262 struct oh323_pvt *pvt;
02263 struct ast_channel *c = NULL;
02264 enum {ext_original, ext_s, ext_i, ext_notexists} try_exten;
02265 char tmp_exten[sizeof(pvt->exten)];
02266
02267 if (h323debug)
02268 ast_debug(1, "Preparing Asterisk to answer for %s\n", token);
02269
02270
02271 pvt = find_call_locked(call_reference, token);
02272 if (!pvt) {
02273 ast_log(LOG_ERROR, "Something is wrong: answer_call\n");
02274 return 0;
02275 }
02276
02277 ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten));
02278
02279
02280 if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) {
02281 if (tmp_exten[0] == 's')
02282 try_exten = ext_s;
02283 else if (tmp_exten[0] == 'i')
02284 try_exten = ext_i;
02285 else
02286 try_exten = ext_original;
02287 } else
02288 try_exten = ext_original;
02289 do {
02290 if (ast_exists_extension(NULL, pvt->context, tmp_exten, 1, NULL))
02291 break;
02292 switch (try_exten) {
02293 case ext_original:
02294 tmp_exten[0] = 's';
02295 tmp_exten[1] = '\0';
02296 try_exten = ext_s;
02297 break;
02298 case ext_s:
02299 tmp_exten[0] = 'i';
02300 try_exten = ext_i;
02301 break;
02302 case ext_i:
02303 try_exten = ext_notexists;
02304 break;
02305 default:
02306 break;
02307 }
02308 } while (try_exten != ext_notexists);
02309
02310
02311 if (try_exten == ext_notexists) {
02312 ast_log(LOG_NOTICE, "Dropping call because extensions '%s', 's' and 'i' doesn't exists in context [%s]\n", pvt->exten, pvt->context);
02313 ast_mutex_unlock(&pvt->lock);
02314 h323_clear_call(token, AST_CAUSE_UNALLOCATED);
02315 return 0;
02316 } else if ((try_exten != ext_original) && (strcmp(pvt->exten, tmp_exten) != 0)) {
02317 if (h323debug)
02318 ast_debug(1, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context);
02319 ast_copy_string(pvt->exten, tmp_exten, sizeof(pvt->exten));
02320 }
02321
02322
02323 c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token, NULL);
02324
02325
02326 ast_mutex_unlock(&pvt->lock);
02327 if (!c) {
02328 ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n");
02329 return 0;
02330 }
02331 return 1;
02332 }
02333
02334
02335
02336
02337
02338
02339 static int setup_outgoing_call(call_details_t *cd)
02340 {
02341
02342 cleanup_call_details(cd);
02343
02344 return 1;
02345 }
02346
02347
02348
02349
02350
02351 static void chan_ringing(unsigned call_reference, const char *token)
02352 {
02353 struct oh323_pvt *pvt;
02354
02355 if (h323debug)
02356 ast_debug(1, "Ringing on %s\n", token);
02357
02358 pvt = find_call_locked(call_reference, token);
02359 if (!pvt) {
02360 ast_log(LOG_ERROR, "Something is wrong: ringing\n");
02361 return;
02362 }
02363 if (!pvt->owner) {
02364 ast_mutex_unlock(&pvt->lock);
02365 ast_log(LOG_ERROR, "Channel has no owner\n");
02366 return;
02367 }
02368 update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING);
02369 ast_mutex_unlock(&pvt->lock);
02370 return;
02371 }
02372
02373
02374
02375
02376
02377 static void cleanup_connection(unsigned call_reference, const char *call_token)
02378 {
02379 struct oh323_pvt *pvt;
02380
02381 if (h323debug)
02382 ast_debug(1, "Cleaning connection to %s\n", call_token);
02383
02384 while (1) {
02385 pvt = find_call_locked(call_reference, call_token);
02386 if (!pvt) {
02387 if (h323debug)
02388 ast_debug(1, "No connection for %s\n", call_token);
02389 return;
02390 }
02391 if (!pvt->owner || !ast_channel_trylock(pvt->owner))
02392 break;
02393 #if 1
02394 ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token);
02395 #ifdef DEBUG_THREADS
02396
02397
02398
02399
02400
02401 #endif
02402 #endif
02403 ast_mutex_unlock(&pvt->lock);
02404 usleep(1);
02405 }
02406 if (pvt->rtp) {
02407
02408 ast_rtp_instance_destroy(pvt->rtp);
02409 pvt->rtp = NULL;
02410 }
02411
02412 if (pvt->vad) {
02413 ast_dsp_free(pvt->vad);
02414 pvt->vad = NULL;
02415 }
02416 cleanup_call_details(&pvt->cd);
02417 pvt->alreadygone = 1;
02418
02419 if (pvt->owner) {
02420 pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02421 ast_queue_hangup(pvt->owner);
02422 ast_channel_unlock(pvt->owner);
02423 }
02424 ast_mutex_unlock(&pvt->lock);
02425 if (h323debug)
02426 ast_debug(1, "Connection to %s cleaned\n", call_token);
02427 return;
02428 }
02429
02430 static void hangup_connection(unsigned int call_reference, const char *token, int cause)
02431 {
02432 struct oh323_pvt *pvt;
02433
02434 if (h323debug)
02435 ast_debug(1, "Hanging up connection to %s with cause %d\n", token, cause);
02436
02437 pvt = find_call_locked(call_reference, token);
02438 if (!pvt) {
02439 if (h323debug)
02440 ast_debug(1, "Connection to %s already cleared\n", token);
02441 return;
02442 }
02443 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02444 pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02445 pvt->owner->hangupcause = pvt->hangupcause = cause;
02446 ast_queue_hangup_with_cause(pvt->owner, cause);
02447 ast_channel_unlock(pvt->owner);
02448 }
02449 else {
02450 pvt->needhangup = 1;
02451 pvt->hangupcause = cause;
02452 if (h323debug)
02453 ast_debug(1, "Hangup for %s is pending\n", token);
02454 }
02455 ast_mutex_unlock(&pvt->lock);
02456 }
02457
02458 static void set_dtmf_payload(unsigned call_reference, const char *token, int payload, int is_cisco)
02459 {
02460 struct oh323_pvt *pvt;
02461
02462 if (h323debug)
02463 ast_debug(1, "Setting %s DTMF payload to %d on %s\n", (is_cisco ? "Cisco" : "RFC2833"), payload, token);
02464
02465 pvt = find_call_locked(call_reference, token);
02466 if (!pvt) {
02467 return;
02468 }
02469 if (pvt->rtp) {
02470 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);
02471 }
02472 pvt->dtmf_pt[is_cisco ? 1 : 0] = payload;
02473 ast_mutex_unlock(&pvt->lock);
02474 if (h323debug)
02475 ast_debug(1, "DTMF payload on %s set to %d\n", token, payload);
02476 }
02477
02478 static void set_peer_capabilities(unsigned call_reference, const char *token, int capabilities, struct ast_codec_pref *prefs)
02479 {
02480 struct oh323_pvt *pvt;
02481
02482 if (h323debug)
02483 ast_debug(1, "Got remote capabilities from connection %s\n", token);
02484
02485 pvt = find_call_locked(call_reference, token);
02486 if (!pvt)
02487 return;
02488 pvt->peercapability = capabilities;
02489 pvt->jointcapability = pvt->options.capability & capabilities;
02490 if (prefs) {
02491 memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs));
02492 if (h323debug) {
02493 int i;
02494 for (i = 0; i < 32; ++i) {
02495 if (!prefs->order[i])
02496 break;
02497 ast_debug(1, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]);
02498 }
02499 }
02500 if (pvt->rtp) {
02501 if (pvt->options.autoframing) {
02502 ast_debug(2, "Autoframing option set, using peer's packetization settings\n");
02503 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
02504 } else {
02505 ast_debug(2, "Autoframing option not set, ignoring peer's packetization settings\n");
02506 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->options.prefs);
02507 }
02508 }
02509 }
02510 ast_mutex_unlock(&pvt->lock);
02511 }
02512
02513 static void set_local_capabilities(unsigned call_reference, const char *token)
02514 {
02515 struct oh323_pvt *pvt;
02516 int capability, dtmfmode, pref_codec;
02517 struct ast_codec_pref prefs;
02518
02519 if (h323debug)
02520 ast_debug(1, "Setting capabilities for connection %s\n", token);
02521
02522 pvt = find_call_locked(call_reference, token);
02523 if (!pvt)
02524 return;
02525 capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
02526 dtmfmode = pvt->options.dtmfmode;
02527 prefs = pvt->options.prefs;
02528 pref_codec = pvt->pref_codec;
02529 ast_mutex_unlock(&pvt->lock);
02530 h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
02531
02532 if (h323debug) {
02533 int i;
02534 for (i = 0; i < 32; i++) {
02535 if (!prefs.order[i])
02536 break;
02537 ast_debug(1, "local prefs[%d]=%s:%d\n", i, (prefs.order[i] ? ast_getformatname(1 << (prefs.order[i]-1)) : "<none>"), prefs.framing[i]);
02538 }
02539 ast_debug(1, "Capabilities for connection %s is set\n", token);
02540 }
02541 }
02542
02543 static void remote_hold(unsigned call_reference, const char *token, int is_hold)
02544 {
02545 struct oh323_pvt *pvt;
02546
02547 if (h323debug)
02548 ast_debug(1, "Setting %shold status for connection %s\n", (is_hold ? "" : "un"), token);
02549
02550 pvt = find_call_locked(call_reference, token);
02551 if (!pvt)
02552 return;
02553 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02554 if (is_hold)
02555 ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02556 else
02557 ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02558 ast_channel_unlock(pvt->owner);
02559 }
02560 else {
02561 if (is_hold)
02562 pvt->newcontrol = AST_CONTROL_HOLD;
02563 else
02564 pvt->newcontrol = AST_CONTROL_UNHOLD;
02565 }
02566 ast_mutex_unlock(&pvt->lock);
02567 }
02568
02569 static void *do_monitor(void *data)
02570 {
02571 int res;
02572 int reloading;
02573 struct oh323_pvt *oh323 = NULL;
02574
02575 for(;;) {
02576
02577 ast_mutex_lock(&h323_reload_lock);
02578 reloading = h323_reloading;
02579 h323_reloading = 0;
02580 ast_mutex_unlock(&h323_reload_lock);
02581 if (reloading) {
02582 ast_verb(1, "Reloading H.323\n");
02583 h323_do_reload();
02584 }
02585
02586 if (!ast_mutex_trylock(&iflock)) {
02587 #if 1
02588 do {
02589 for (oh323 = iflist; oh323; oh323 = oh323->next) {
02590 if (!ast_mutex_trylock(&oh323->lock)) {
02591 if (oh323->needdestroy) {
02592 __oh323_destroy(oh323);
02593 break;
02594 }
02595 ast_mutex_unlock(&oh323->lock);
02596 }
02597 }
02598 } while ( 0);
02599 #else
02600 restartsearch:
02601 oh323 = iflist;
02602 while(oh323) {
02603 if (!ast_mutex_trylock(&oh323->lock)) {
02604 if (oh323->needdestroy) {
02605 __oh323_destroy(oh323);
02606 goto restartsearch;
02607 }
02608 ast_mutex_unlock(&oh323->lock);
02609 oh323 = oh323->next;
02610 }
02611 }
02612 #endif
02613 ast_mutex_unlock(&iflock);
02614 } else
02615 oh323 = (struct oh323_pvt *)1;
02616 pthread_testcancel();
02617
02618 res = ast_sched_wait(sched);
02619 if ((res < 0) || (res > 1000)) {
02620 res = 1000;
02621 }
02622
02623 if (oh323)
02624 res = 1;
02625 res = ast_io_wait(io, res);
02626 pthread_testcancel();
02627 ast_mutex_lock(&monlock);
02628 if (res >= 0) {
02629 ast_sched_runq(sched);
02630 }
02631 ast_mutex_unlock(&monlock);
02632 }
02633
02634 return NULL;
02635 }
02636
02637 static int restart_monitor(void)
02638 {
02639
02640 if (ast_mutex_lock(&monlock)) {
02641 ast_log(LOG_WARNING, "Unable to lock monitor\n");
02642 return -1;
02643 }
02644 if (monitor_thread == AST_PTHREADT_STOP) {
02645 ast_mutex_unlock(&monlock);
02646 return 0;
02647 }
02648 if (monitor_thread == pthread_self()) {
02649 ast_mutex_unlock(&monlock);
02650 ast_log(LOG_WARNING, "Cannot kill myself\n");
02651 return -1;
02652 }
02653 if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) {
02654
02655 pthread_kill(monitor_thread, SIGURG);
02656 } else {
02657
02658 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
02659 monitor_thread = AST_PTHREADT_NULL;
02660 ast_mutex_unlock(&monlock);
02661 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
02662 return -1;
02663 }
02664 }
02665 ast_mutex_unlock(&monlock);
02666 return 0;
02667 }
02668
02669 static char *handle_cli_h323_set_trace(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02670 {
02671 switch (cmd) {
02672 case CLI_INIT:
02673 e->command = "h323 set trace [on|off]";
02674 e->usage =
02675 "Usage: h323 set trace (on|off|<trace level>)\n"
02676 " Enable/Disable H.323 stack tracing for debugging purposes\n";
02677 return NULL;
02678 case CLI_GENERATE:
02679 return NULL;
02680 }
02681
02682 if (a->argc != e->args)
02683 return CLI_SHOWUSAGE;
02684 if (!strcasecmp(a->argv[3], "off")) {
02685 h323_debug(0, 0);
02686 ast_cli(a->fd, "H.323 Trace Disabled\n");
02687 } else if (!strcasecmp(a->argv[3], "on")) {
02688 h323_debug(1, 1);
02689 ast_cli(a->fd, "H.323 Trace Enabled\n");
02690 } else {
02691 int tracelevel = atoi(a->argv[3]);
02692 h323_debug(1, tracelevel);
02693 ast_cli(a->fd, "H.323 Trace Enabled (Trace Level: %d)\n", tracelevel);
02694 }
02695 return CLI_SUCCESS;
02696 }
02697
02698 static char *handle_cli_h323_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02699 {
02700 switch (cmd) {
02701 case CLI_INIT:
02702 e->command = "h323 set debug [on|off]";
02703 e->usage =
02704 "Usage: h323 set debug [on|off]\n"
02705 " Enable/Disable H.323 debugging output\n";
02706 return NULL;
02707 case CLI_GENERATE:
02708 return NULL;
02709 }
02710
02711 if (a->argc != e->args)
02712 return CLI_SHOWUSAGE;
02713 if (strcasecmp(a->argv[3], "on") && strcasecmp(a->argv[3], "off"))
02714 return CLI_SHOWUSAGE;
02715
02716 h323debug = (strcasecmp(a->argv[3], "on")) ? 0 : 1;
02717 ast_cli(a->fd, "H.323 Debugging %s\n", h323debug ? "Enabled" : "Disabled");
02718 return CLI_SUCCESS;
02719 }
02720
02721 static char *handle_cli_h323_cycle_gk(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02722 {
02723 switch (cmd) {
02724 case CLI_INIT:
02725 e->command = "h323 cycle gk";
02726 e->usage =
02727 "Usage: h323 cycle gk\n"
02728 " Manually re-register with the Gatekeper (Currently Disabled)\n";
02729 return NULL;
02730 case CLI_GENERATE:
02731 return NULL;
02732 }
02733
02734 if (a->argc != 3)
02735 return CLI_SHOWUSAGE;
02736
02737 h323_gk_urq();
02738
02739
02740 if (!gatekeeper_disable) {
02741 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
02742 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
02743 }
02744 }
02745 return CLI_SUCCESS;
02746 }
02747
02748 static char *handle_cli_h323_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02749 {
02750 switch (cmd) {
02751 case CLI_INIT:
02752 e->command = "h323 hangup";
02753 e->usage =
02754 "Usage: h323 hangup <token>\n"
02755 " Manually try to hang up the call identified by <token>\n";
02756 return NULL;
02757 case CLI_GENERATE:
02758 return NULL;
02759 }
02760
02761 if (a->argc != 3)
02762 return CLI_SHOWUSAGE;
02763 if (h323_soft_hangup(a->argv[2])) {
02764 ast_verb(3, "Hangup succeeded on %s\n", a->argv[2]);
02765 } else {
02766 ast_verb(3, "Hangup failed for %s\n", a->argv[2]);
02767 }
02768 return CLI_SUCCESS;
02769 }
02770
02771 static char *handle_cli_h323_show_tokens(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02772 {
02773 switch (cmd) {
02774 case CLI_INIT:
02775 e->command = "h323 show tokens";
02776 e->usage =
02777 "Usage: h323 show tokens\n"
02778 " Print out all active call tokens\n";
02779 return NULL;
02780 case CLI_GENERATE:
02781 return NULL;
02782 }
02783
02784 if (a->argc != 3)
02785 return CLI_SHOWUSAGE;
02786
02787 h323_show_tokens();
02788
02789 return CLI_SUCCESS;
02790 }
02791
02792 static char *handle_cli_h323_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02793 {
02794 switch (cmd) {
02795 case CLI_INIT:
02796 e->command = "h323 show version";
02797 e->usage =
02798 "Usage: h323 show version\n"
02799 " Show the version of the H.323 library in use\n";
02800 return NULL;
02801 case CLI_GENERATE:
02802 return NULL;
02803 }
02804
02805 if (a->argc != 3)
02806 return CLI_SHOWUSAGE;
02807
02808 h323_show_version();
02809
02810 return CLI_SUCCESS;
02811 }
02812
02813 static struct ast_cli_entry cli_h323[] = {
02814 AST_CLI_DEFINE(handle_cli_h323_set_trace, "Enable/Disable H.323 Stack Tracing"),
02815 AST_CLI_DEFINE(handle_cli_h323_set_debug, "Enable/Disable H.323 Debugging"),
02816 AST_CLI_DEFINE(handle_cli_h323_cycle_gk, "Manually re-register with the Gatekeper"),
02817 AST_CLI_DEFINE(handle_cli_h323_hangup, "Manually try to hang up a call"),
02818 AST_CLI_DEFINE(handle_cli_h323_show_tokens, "Show all active call tokens"),
02819 AST_CLI_DEFINE(handle_cli_h323_show_version, "Show the version of the H.323 library in use"),
02820 };
02821
02822 static void delete_users(void)
02823 {
02824 int pruned = 0;
02825
02826
02827 ASTOBJ_CONTAINER_WRLOCK(&userl);
02828 ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
02829 ASTOBJ_RDLOCK(iterator);
02830 ASTOBJ_MARK(iterator);
02831 ++pruned;
02832 ASTOBJ_UNLOCK(iterator);
02833 } while (0) );
02834 if (pruned) {
02835 ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
02836 }
02837 ASTOBJ_CONTAINER_UNLOCK(&userl);
02838
02839 ASTOBJ_CONTAINER_WRLOCK(&peerl);
02840 ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
02841 ASTOBJ_RDLOCK(iterator);
02842 ASTOBJ_MARK(iterator);
02843 ASTOBJ_UNLOCK(iterator);
02844 } while (0) );
02845 ASTOBJ_CONTAINER_UNLOCK(&peerl);
02846 }
02847
02848 static void delete_aliases(void)
02849 {
02850 int pruned = 0;
02851
02852
02853 ASTOBJ_CONTAINER_WRLOCK(&aliasl);
02854 ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
02855 ASTOBJ_RDLOCK(iterator);
02856 ASTOBJ_MARK(iterator);
02857 ++pruned;
02858 ASTOBJ_UNLOCK(iterator);
02859 } while (0) );
02860 if (pruned) {
02861 ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
02862 }
02863 ASTOBJ_CONTAINER_UNLOCK(&aliasl);
02864 }
02865
02866 static void prune_peers(void)
02867 {
02868
02869 ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
02870 }
02871
02872 static int reload_config(int is_reload)
02873 {
02874 struct ast_config *cfg, *ucfg;
02875 struct ast_variable *v;
02876 struct oh323_peer *peer = NULL;
02877 struct oh323_user *user = NULL;
02878 struct oh323_alias *alias = NULL;
02879 struct ast_hostent ahp; struct hostent *hp;
02880 char *cat;
02881 const char *utype;
02882 int is_user, is_peer, is_alias;
02883 char _gatekeeper[100];
02884 int gk_discover, gk_disable, gk_changed;
02885 struct ast_flags config_flags = { is_reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02886
02887 cfg = ast_config_load(config, config_flags);
02888
02889
02890 if (!cfg) {
02891 ast_log(LOG_NOTICE, "Unable to load config %s, H.323 disabled\n", config);
02892 return 1;
02893 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
02894 ucfg = ast_config_load("users.conf", config_flags);
02895 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
02896 return 0;
02897 } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
02898 ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Aborting.\n");
02899 return 0;
02900 }
02901 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
02902 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
02903 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
02904 ast_config_destroy(ucfg);
02905 return 0;
02906 }
02907 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02908 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
02909 return 0;
02910 } else {
02911 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
02912 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
02913 ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Aborting.\n");
02914 ast_config_destroy(cfg);
02915 return 0;
02916 }
02917 }
02918
02919 if (is_reload) {
02920 delete_users();
02921 delete_aliases();
02922 prune_peers();
02923 }
02924
02925
02926 if (!h323_end_point_exist()) {
02927 h323_end_point_create();
02928 }
02929 ast_copy_string(_gatekeeper, gatekeeper, sizeof(_gatekeeper));
02930 gk_discover = gatekeeper_discover;
02931 gk_disable = gatekeeper_disable;
02932 memset(&bindaddr, 0, sizeof(bindaddr));
02933 memset(&global_options, 0, sizeof(global_options));
02934 global_options.fastStart = 1;
02935 global_options.h245Tunneling = 1;
02936 global_options.dtmfcodec[0] = H323_DTMF_RFC2833_PT;
02937 global_options.dtmfcodec[1] = H323_DTMF_CISCO_PT;
02938 global_options.dtmfmode = 0;
02939 global_options.holdHandling = 0;
02940 global_options.capability = GLOBAL_CAPABILITY;
02941 global_options.bridge = 1;
02942 global_options.autoframing = 0;
02943 strcpy(default_context, "default");
02944 h323_signalling_port = 1720;
02945 gatekeeper_disable = 1;
02946 gatekeeper_discover = 0;
02947 gkroute = 0;
02948 userbyalias = 1;
02949 acceptAnonymous = 1;
02950 tos = 0;
02951 cos = 0;
02952
02953
02954 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
02955
02956 if (ucfg) {
02957 struct ast_variable *gen;
02958 int genhas_h323;
02959 const char *has_h323;
02960
02961 genhas_h323 = ast_true(ast_variable_retrieve(ucfg, "general", "hash323"));
02962 gen = ast_variable_browse(ucfg, "general");
02963 for (cat = ast_category_browse(ucfg, NULL); cat; cat = ast_category_browse(ucfg, cat)) {
02964 if (strcasecmp(cat, "general")) {
02965 has_h323 = ast_variable_retrieve(ucfg, cat, "hash323");
02966 if (ast_true(has_h323) || (!has_h323 && genhas_h323)) {
02967 user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
02968 if (user) {
02969 ASTOBJ_CONTAINER_LINK(&userl, user);
02970 ASTOBJ_UNREF(user, oh323_destroy_user);
02971 }
02972 peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
02973 if (peer) {
02974 ASTOBJ_CONTAINER_LINK(&peerl, peer);
02975 ASTOBJ_UNREF(peer, oh323_destroy_peer);
02976 }
02977 }
02978 }
02979 }
02980 ast_config_destroy(ucfg);
02981 }
02982
02983 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
02984
02985 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
02986 continue;
02987
02988 if (!strcasecmp(v->name, "port")) {
02989 h323_signalling_port = (int)strtol(v->value, NULL, 10);
02990 } else if (!strcasecmp(v->name, "bindaddr")) {
02991 if (!(hp = ast_gethostbyname(v->value, &ahp))) {
02992 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
02993 } else {
02994 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
02995 }
02996 } else if (!strcasecmp(v->name, "tos")) {
02997 ast_log(LOG_WARNING, "The \"tos\" setting is deprecated in this version of Asterisk. Please change to \"tos_audio\".\n");
02998 if (ast_str2tos(v->value, &tos)) {
02999 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
03000 }
03001 } else if (!strcasecmp(v->name, "tos_audio")) {
03002 if (ast_str2tos(v->value, &tos)) {
03003 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
03004 }
03005 } else if (!strcasecmp(v->name, "cos")) {
03006 ast_log(LOG_WARNING, "The \"cos\" setting is deprecated in this version of Asterisk. Please change to \"cos_audio\".\n");
03007 if (ast_str2cos(v->value, &cos)) {
03008 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
03009 }
03010 } else if (!strcasecmp(v->name, "cos_audio")) {
03011 if (ast_str2cos(v->value, &cos)) {
03012 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
03013 }
03014 } else if (!strcasecmp(v->name, "gatekeeper")) {
03015 if (!strcasecmp(v->value, "DISABLE")) {
03016 gatekeeper_disable = 1;
03017 } else if (!strcasecmp(v->value, "DISCOVER")) {
03018 gatekeeper_disable = 0;
03019 gatekeeper_discover = 1;
03020 } else {
03021 gatekeeper_disable = 0;
03022 ast_copy_string(gatekeeper, v->value, sizeof(gatekeeper));
03023 }
03024 } else if (!strcasecmp(v->name, "secret")) {
03025 ast_copy_string(secret, v->value, sizeof(secret));
03026 } else if (!strcasecmp(v->name, "AllowGKRouted")) {
03027 gkroute = ast_true(v->value);
03028 } else if (!strcasecmp(v->name, "context")) {
03029 ast_copy_string(default_context, v->value, sizeof(default_context));
03030 ast_verb(2, "Setting default context to %s\n", default_context);
03031 } else if (!strcasecmp(v->name, "UserByAlias")) {
03032 userbyalias = ast_true(v->value);
03033 } else if (!strcasecmp(v->name, "AcceptAnonymous")) {
03034 acceptAnonymous = ast_true(v->value);
03035 } else if (!update_common_options(v, &global_options)) {
03036
03037 }
03038 }
03039 if (!global_options.dtmfmode)
03040 global_options.dtmfmode = H323_DTMF_RFC2833;
03041 if (global_options.holdHandling == ~0)
03042 global_options.holdHandling = 0;
03043 else if (!global_options.holdHandling)
03044 global_options.holdHandling = H323_HOLD_H450;
03045
03046 for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
03047 if (strcasecmp(cat, "general")) {
03048 utype = ast_variable_retrieve(cfg, cat, "type");
03049 if (utype) {
03050 is_user = is_peer = is_alias = 0;
03051 if (!strcasecmp(utype, "user"))
03052 is_user = 1;
03053 else if (!strcasecmp(utype, "peer"))
03054 is_peer = 1;
03055 else if (!strcasecmp(utype, "friend"))
03056 is_user = is_peer = 1;
03057 else if (!strcasecmp(utype, "h323") || !strcasecmp(utype, "alias"))
03058 is_alias = 1;
03059 else {
03060 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config);
03061 continue;
03062 }
03063 if (is_user) {
03064 user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
03065 if (user) {
03066 ASTOBJ_CONTAINER_LINK(&userl, user);
03067 ASTOBJ_UNREF(user, oh323_destroy_user);
03068 }
03069 }
03070 if (is_peer) {
03071 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
03072 if (peer) {
03073 ASTOBJ_CONTAINER_LINK(&peerl, peer);
03074 ASTOBJ_UNREF(peer, oh323_destroy_peer);
03075 }
03076 }
03077 if (is_alias) {
03078 alias = build_alias(cat, ast_variable_browse(cfg, cat), NULL, 0);
03079 if (alias) {
03080 ASTOBJ_CONTAINER_LINK(&aliasl, alias);
03081 ASTOBJ_UNREF(alias, oh323_destroy_alias);
03082 }
03083 }
03084 } else {
03085 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
03086 }
03087 }
03088 }
03089 ast_config_destroy(cfg);
03090
03091
03092 ASTOBJ_CONTAINER_WRLOCK(&aliasl);
03093 ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
03094 ASTOBJ_RDLOCK(iterator);
03095 if (h323_set_alias(iterator)) {
03096 ast_log(LOG_ERROR, "Alias %s rejected by endpoint\n", alias->name);
03097 ASTOBJ_UNLOCK(iterator);
03098 continue;
03099 }
03100 ASTOBJ_UNLOCK(iterator);
03101 } while (0) );
03102 ASTOBJ_CONTAINER_UNLOCK(&aliasl);
03103
03104
03105 gk_changed = 0;
03106 if (gatekeeper_disable != gk_disable)
03107 gk_changed = is_reload;
03108 else if(!gatekeeper_disable && (gatekeeper_discover != gk_discover))
03109 gk_changed = is_reload;
03110 else if(!gatekeeper_disable && (strncmp(_gatekeeper, gatekeeper, sizeof(_gatekeeper)) != 0))
03111 gk_changed = is_reload;
03112 if (gk_changed) {
03113 if(!gk_disable)
03114 h323_gk_urq();
03115 if (!gatekeeper_disable) {
03116 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03117 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03118 gatekeeper_disable = 1;
03119 }
03120 }
03121 }
03122 return 0;
03123 }
03124
03125 static int h323_reload(void)
03126 {
03127 ast_mutex_lock(&h323_reload_lock);
03128 if (h323_reloading) {
03129 ast_verbose("Previous H.323 reload not yet done\n");
03130 } else {
03131 h323_reloading = 1;
03132 }
03133 ast_mutex_unlock(&h323_reload_lock);
03134 restart_monitor();
03135 return 0;
03136 }
03137
03138 static char *handle_cli_h323_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03139 {
03140 switch (cmd) {
03141 case CLI_INIT:
03142 e->command = "h323 reload";
03143 e->usage =
03144 "Usage: h323 reload\n"
03145 " Reloads H.323 configuration from h323.conf\n";
03146 return NULL;
03147 case CLI_GENERATE:
03148 return NULL;
03149 }
03150
03151 if (a->argc != 2)
03152 return CLI_SHOWUSAGE;
03153
03154 h323_reload();
03155
03156 return CLI_SUCCESS;
03157 }
03158
03159 static int h323_do_reload(void)
03160 {
03161 reload_config(1);
03162 return 0;
03163 }
03164
03165 static int reload(void)
03166 {
03167 if (!sched || !io) {
03168 ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03169 return 0;
03170 }
03171 return h323_reload();
03172 }
03173
03174 static struct ast_cli_entry cli_h323_reload =
03175 AST_CLI_DEFINE(handle_cli_h323_reload, "Reload H.323 configuration");
03176
03177 static enum ast_rtp_glue_result oh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
03178 {
03179 struct oh323_pvt *pvt;
03180 enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
03181
03182 if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
03183 return AST_RTP_GLUE_RESULT_FORBID;
03184
03185 ast_mutex_lock(&pvt->lock);
03186 *instance = pvt->rtp ? ao2_ref(pvt->rtp, +1), pvt->rtp : NULL;
03187 #if 0
03188 if (pvt->options.bridge) {
03189 res = AST_RTP_GLUE_RESULT_REMOTE;
03190 }
03191 #endif
03192 ast_mutex_unlock(&pvt->lock);
03193
03194 return res;
03195 }
03196
03197 static char *convertcap(format_t cap)
03198 {
03199 switch (cap) {
03200 case AST_FORMAT_G723_1:
03201 return "G.723";
03202 case AST_FORMAT_GSM:
03203 return "GSM";
03204 case AST_FORMAT_ULAW:
03205 return "ULAW";
03206 case AST_FORMAT_ALAW:
03207 return "ALAW";
03208 case AST_FORMAT_G722:
03209 return "G.722";
03210 case AST_FORMAT_ADPCM:
03211 return "G.728";
03212 case AST_FORMAT_G729A:
03213 return "G.729";
03214 case AST_FORMAT_SPEEX:
03215 return "SPEEX";
03216 case AST_FORMAT_ILBC:
03217 return "ILBC";
03218 default:
03219 ast_log(LOG_NOTICE, "Don't know how to deal with mode %" PRId64 "\n", cap);
03220 return NULL;
03221 }
03222 }
03223
03224 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)
03225 {
03226
03227 struct oh323_pvt *pvt;
03228 struct sockaddr_in them = { 0, };
03229 struct sockaddr_in us = { 0, };
03230 char *mode;
03231
03232 if (!rtp) {
03233 return 0;
03234 }
03235
03236 mode = convertcap(chan->writeformat);
03237 pvt = (struct oh323_pvt *) chan->tech_pvt;
03238 if (!pvt) {
03239 ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
03240 return -1;
03241 }
03242 {
03243 struct ast_sockaddr tmp;
03244
03245 ast_rtp_instance_get_remote_address(rtp, &tmp);
03246 ast_sockaddr_to_sin(&tmp, &them);
03247 ast_rtp_instance_get_local_address(rtp, &tmp);
03248 ast_sockaddr_to_sin(&tmp, &us);
03249 }
03250 #if 0
03251 h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
03252 #endif
03253 return 0;
03254 }
03255
03256 static struct ast_rtp_glue oh323_rtp_glue = {
03257 .type = "H323",
03258 .get_rtp_info = oh323_get_rtp_peer,
03259 .update_peer = oh323_set_rtp_peer,
03260 };
03261
03262 static enum ast_module_load_result load_module(void)
03263 {
03264 int res;
03265
03266 h323debug = 0;
03267 sched = sched_context_create();
03268 if (!sched) {
03269 ast_log(LOG_WARNING, "Unable to create schedule context\n");
03270 return AST_MODULE_LOAD_FAILURE;
03271 }
03272 io = io_context_create();
03273 if (!io) {
03274 ast_log(LOG_WARNING, "Unable to create I/O context\n");
03275 return AST_MODULE_LOAD_FAILURE;
03276 }
03277 ast_cli_register(&cli_h323_reload);
03278 ASTOBJ_CONTAINER_INIT(&userl);
03279 ASTOBJ_CONTAINER_INIT(&peerl);
03280 ASTOBJ_CONTAINER_INIT(&aliasl);
03281 res = reload_config(0);
03282 if (res) {
03283
03284 ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03285 ast_cli_unregister(&cli_h323_reload);
03286 io_context_destroy(io);
03287 io = NULL;
03288 sched_context_destroy(sched);
03289 sched = NULL;
03290 ASTOBJ_CONTAINER_DESTROY(&userl);
03291 ASTOBJ_CONTAINER_DESTROY(&peerl);
03292 ASTOBJ_CONTAINER_DESTROY(&aliasl);
03293 return AST_MODULE_LOAD_DECLINE;
03294 } else {
03295
03296 if (ast_channel_register(&oh323_tech)) {
03297 ast_log(LOG_ERROR, "Unable to register channel class 'H323'\n");
03298 ast_cli_unregister(&cli_h323_reload);
03299 h323_end_process();
03300 io_context_destroy(io);
03301 sched_context_destroy(sched);
03302
03303 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03304 ASTOBJ_CONTAINER_DESTROY(&userl);
03305 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03306 ASTOBJ_CONTAINER_DESTROY(&peerl);
03307 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03308 ASTOBJ_CONTAINER_DESTROY(&aliasl);
03309
03310 return AST_MODULE_LOAD_FAILURE;
03311 }
03312 ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03313
03314 ast_rtp_glue_register(&oh323_rtp_glue);
03315
03316
03317 h323_callback_register(setup_incoming_call,
03318 setup_outgoing_call,
03319 external_rtp_create,
03320 setup_rtp_connection,
03321 cleanup_connection,
03322 chan_ringing,
03323 connection_made,
03324 receive_digit,
03325 answer_call,
03326 progress,
03327 set_dtmf_payload,
03328 hangup_connection,
03329 set_local_capabilities,
03330 set_peer_capabilities,
03331 remote_hold);
03332
03333 if (h323_start_listener(h323_signalling_port, bindaddr)) {
03334 ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
03335 ast_rtp_glue_unregister(&oh323_rtp_glue);
03336 ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03337 ast_cli_unregister(&cli_h323_reload);
03338 h323_end_process();
03339 io_context_destroy(io);
03340 sched_context_destroy(sched);
03341
03342 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03343 ASTOBJ_CONTAINER_DESTROY(&userl);
03344 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03345 ASTOBJ_CONTAINER_DESTROY(&peerl);
03346 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03347 ASTOBJ_CONTAINER_DESTROY(&aliasl);
03348
03349 return AST_MODULE_LOAD_DECLINE;
03350 }
03351
03352 if (!gatekeeper_disable) {
03353 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03354 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03355 gatekeeper_disable = 1;
03356 res = AST_MODULE_LOAD_SUCCESS;
03357 }
03358 }
03359
03360 restart_monitor();
03361 }
03362 return res;
03363 }
03364
03365 static int unload_module(void)
03366 {
03367 struct oh323_pvt *p, *pl;
03368
03369
03370 ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03371 ast_cli_unregister(&cli_h323_reload);
03372
03373 ast_channel_unregister(&oh323_tech);
03374 ast_rtp_glue_unregister(&oh323_rtp_glue);
03375
03376 if (!ast_mutex_lock(&iflock)) {
03377
03378 p = iflist;
03379 while(p) {
03380 if (p->owner) {
03381 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
03382 }
03383 p = p->next;
03384 }
03385 iflist = NULL;
03386 ast_mutex_unlock(&iflock);
03387 } else {
03388 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03389 return -1;
03390 }
03391 if (!ast_mutex_lock(&monlock)) {
03392 if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
03393 if (monitor_thread != pthread_self()) {
03394 pthread_cancel(monitor_thread);
03395 }
03396 pthread_kill(monitor_thread, SIGURG);
03397 pthread_join(monitor_thread, NULL);
03398 }
03399 monitor_thread = AST_PTHREADT_STOP;
03400 ast_mutex_unlock(&monlock);
03401 } else {
03402 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
03403 return -1;
03404 }
03405 if (!ast_mutex_lock(&iflock)) {
03406
03407 p = iflist;
03408 while(p) {
03409 pl = p;
03410 p = p->next;
03411
03412 ast_mutex_destroy(&pl->lock);
03413 ast_free(pl);
03414 }
03415 iflist = NULL;
03416 ast_mutex_unlock(&iflock);
03417 } else {
03418 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03419 return -1;
03420 }
03421 if (!gatekeeper_disable)
03422 h323_gk_urq();
03423 h323_end_process();
03424 if (io)
03425 io_context_destroy(io);
03426 if (sched)
03427 sched_context_destroy(sched);
03428
03429 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03430 ASTOBJ_CONTAINER_DESTROY(&userl);
03431 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03432 ASTOBJ_CONTAINER_DESTROY(&peerl);
03433 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03434 ASTOBJ_CONTAINER_DESTROY(&aliasl);
03435
03436 return 0;
03437 }
03438
03439 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "The NuFone Network's OpenH323 Channel Driver",
03440 .load = load_module,
03441 .unload = unload_module,
03442 .reload = reload,
03443 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
03444 );