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