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