Newer
Older
ast_debug(1, "Got UDPTL %u/%d len %d for %s\n",
f->frametype, f->subclass.integer, f->datalen, ast_channel_name(ast));
p->lastrtprx = time(NULL);
break;
default:
f = &null_frame;
}
if (f && p->owner && !p->faxmode && (f->frametype == AST_FRAME_VOICE)) {
/* We already hold the channel lock */
if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(p->owner), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
struct ast_format_cap *caps;
ast_debug(1, "Oooh, voice format changed to %s\n", ast_format_get_name(f->subclass.format));
caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (caps) {
ast_format_cap_append(caps, f->subclass.format, 0);
ast_channel_nativeformats_set(p->owner, caps);
ao2_ref(caps, -1);
}
ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
ast_set_write_format(p->owner, ast_channel_writeformat(p->owner));
}
if (((p->dtmfmode & H323_DTMF_INBAND) || (p->faxdetect & FAXDETECT_CNG)) && p->vad &&
((ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) ||
(ast_format_cmp(f->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) ||
(ast_format_cmp(f->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL))) {
dfr = ast_frdup(f);
dfr = ast_dsp_process(p->owner, p->vad, dfr);
}
} else {
return f;
}
/* process INBAND DTMF*/
if (dfr && (dfr->frametype == AST_FRAME_DTMF) && ((dfr->subclass.integer == 'f') || (dfr->subclass.integer == 'e'))) {
ast_debug(1, "* Detected FAX Tone %s\n", (dfr->subclass.integer == 'e') ? "CED" : "CNG");
/* Switch to T.38 ON CED*/
if (!p->faxmode && !p->chmodepend && (dfr->subclass.integer == 'e') && (p->t38support != T38_DISABLED)) {
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "request to change %s to t.38 because fax ced\n", p->callToken);
p->chmodepend = 1;
p->faxdetected = 1;
ooRequestChangeMode(p->callToken, 1);
} else if ((dfr->subclass.integer == 'f') && !p->faxdetected) {
const char *target_context = S_OR(ast_channel_macrocontext(p->owner), ast_channel_context(p->owner));
if ((strcmp(ast_channel_exten(p->owner), "fax")) &&
(ast_exists_extension(p->owner, target_context, "fax", 1,
S_COR(ast_channel_caller(p->owner)->id.number.valid, ast_channel_caller(p->owner)->id.number.str, NULL)))) {
ast_verb(2, "Redirecting '%s' to fax extension due to CNG detection\n", ast_channel_name(p->owner));
pbx_builtin_setvar_helper(p->owner, "FAXEXTEN", ast_channel_exten(p->owner));
if (ast_async_goto(p->owner, target_context, "fax", 1)) {
ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(p->owner),target_context);
}
}
} else if (dfr && dfr->frametype == AST_FRAME_DTMF) {
ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass.integer);
ast_frfree(f);
return dfr;
}
if (dfr) {
ast_frfree(dfr);
}
return f;
}
void onModeChanged(ooCallData *call, int t38mode) {
struct ooh323_pvt *p;
p = find_call(call);
if (!p) {
ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
return;
}
ast_mutex_lock(&p->lock);
if (gH323Debug)
ast_debug(1, "change mode to %d for %s\n", t38mode, call->callToken);
if (t38mode == p->faxmode) {
ast_debug(1, "mode for %s is already %d\n", call->callToken,
t38mode);
ast_mutex_unlock(&p->lock);
return;
}
if (p->owner) {
while (p->owner && ast_channel_trylock(p->owner)) {
ast_debug(1,"Failed to grab lock, trying again\n");
DEADLOCK_AVOIDANCE(&p->lock);
}
if (!p->owner) {
ast_mutex_unlock(&p->lock);
ast_log(LOG_ERROR, "Channel has no owner\n");
return;
}
} else {
ast_mutex_unlock(&p->lock);
ast_log(LOG_ERROR, "Channel has no owner\n");
return;
}
if (t38mode) {
if (p->t38support == T38_ENABLED) {
struct ast_control_t38_parameters parameters = { .request_response = 0 };
if ((p->faxdetect & FAXDETECT_T38) && !p->faxdetected) {
const char *target_context;
ast_debug(1, "* Detected T.38 Request\n");
target_context = S_OR(ast_channel_macrocontext(p->owner), ast_channel_context(p->owner));
if ((strcmp(ast_channel_exten(p->owner), "fax")) &&
(ast_exists_extension(p->owner, target_context, "fax", 1,
S_COR(ast_channel_caller(p->owner)->id.number.valid, ast_channel_caller(p->owner)->id.number.str, NULL)))) {
ast_verb(2, "Redirecting '%s' to fax extension due to CNG detection\n", ast_channel_name(p->owner));
pbx_builtin_setvar_helper(p->owner, "FAXEXTEN", ast_channel_exten(p->owner));
if (ast_async_goto(p->owner, target_context, "fax", 1)) {
ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(p->owner),target_context);
}
}
p->faxdetected = 1;
}
/* AST_T38_CONTROL mode */
parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
if (call->T38FarMaxDatagram) {
ast_udptl_set_far_max_datagram(p->udptl, call->T38FarMaxDatagram);
} else {
ast_udptl_set_far_max_datagram(p->udptl, 144);
}
if (call->T38Version) {
parameters.version = call->T38Version;
}
parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
parameters.rate = AST_T38_RATE_14400;
ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS,
¶meters, sizeof(parameters));
p->faxmode = 1;
}
} else {
if (p->t38support == T38_ENABLED) {
struct ast_control_t38_parameters parameters = { .request_response = 0 };
parameters.request_response = AST_T38_REQUEST_TERMINATE;
parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
parameters.rate = AST_T38_RATE_14400;
ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS,
¶meters, sizeof(parameters));
}
p->faxmode = 0;
p->t38_init = 0;
}
p->chmodepend = 0;
ast_channel_unlock(p->owner);
ast_mutex_unlock(&p->lock);
}
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
int ooh323_convert_hangupcause_asteriskToH323(int cause)
{
switch (cause) {
case AST_CAUSE_CALL_REJECTED:
return OO_REASON_REMOTE_REJECTED;
case AST_CAUSE_UNALLOCATED:
return OO_REASON_NOUSER;
case AST_CAUSE_BUSY:
return OO_REASON_REMOTE_BUSY;
case AST_CAUSE_BEARERCAPABILITY_NOTAVAIL:
return OO_REASON_NOCOMMON_CAPABILITIES;
case AST_CAUSE_CONGESTION:
return OO_REASON_REMOTE_BUSY;
case AST_CAUSE_NO_ANSWER:
return OO_REASON_REMOTE_NOANSWER;
case AST_CAUSE_NORMAL:
return OO_REASON_REMOTE_CLEARED;
case AST_CAUSE_FAILURE:
default:
return OO_REASON_UNKNOWN;
}
return 0;
}
int ooh323_convert_hangupcause_h323ToAsterisk(int cause)
{
switch (cause) {
case OO_REASON_REMOTE_REJECTED:
return AST_CAUSE_CALL_REJECTED;
return AST_CAUSE_UNALLOCATED;
case OO_REASON_REMOTE_BUSY:
case OO_REASON_LOCAL_BUSY:
return AST_CAUSE_BUSY;
case OO_REASON_NOCOMMON_CAPABILITIES: /* No codecs approved */
return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
case OO_REASON_REMOTE_CONGESTED:
case OO_REASON_LOCAL_CONGESTED:
return AST_CAUSE_CONGESTION;
case OO_REASON_REMOTE_NOANSWER:
return AST_CAUSE_NO_ANSWER;
case OO_REASON_INVALIDMESSAGE:
case OO_REASON_TRANSPORTFAILURE:
return AST_CAUSE_FAILURE;
case OO_REASON_REMOTE_CLEARED:
return AST_CAUSE_NORMAL;
default:
return AST_CAUSE_NORMAL;
}
/* Never reached */
return 0;
}
#if 0
void ast_ooh323c_exit()
{
ooGkClientDestroy();
}
#endif
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Objective Systems H323 Channel",
Rodrigo Ramírez Norambuena
committed
.support_level = AST_MODULE_SUPPORT_EXTENDED,
.load = load_module,
.unload = unload_module,
.reload = reload_module,
.load_pri = AST_MODPRI_CHANNEL_DRIVER,
.requires = "udptl",