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