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