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