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