Skip to content
Snippets Groups Projects
chan_ooh323.c 148 KiB
Newer Older
  • Learn to ignore specific revisions
  • 			 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);
    
    	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)
    
    				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);
    
    				}
    				p->faxdetected = 1;
    
    				ast_frfree(dfr);
    
    				return &ast_null_frame;
    
    	} 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);
    
    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) {
    
    		if (gH323Debug)
    
    			ast_debug(1, "mode for %s is already %d\n", call->callToken,
    					t38mode);
    
    		p->chmodepend = 0;
    
    		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) {
    
    			p->chmodepend = 0;
    
    			ast_mutex_unlock(&p->lock);
    			ast_log(LOG_ERROR, "Channel has no owner\n");
    			return;
    		}
    	} else {
    
    		p->chmodepend = 0;
    
    		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);
    
    
    /* 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,
    
    							&parameters, 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,
    
    							&parameters, sizeof(parameters));
    		}
    		p->faxmode = 0;
    
    		p->faxdetected = 0;
    
    		p->t38_init = 0;
    	}
    
    	p->chmodepend = 0;
    	ast_channel_unlock(p->owner);
    	ast_mutex_unlock(&p->lock);
    }
    
    
    
    
    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;
    
    	case OO_REASON_NOUSER:
    
    		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_UNKNOWN:
    
    	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",
    
    	.support_level = AST_MODULE_SUPPORT_EXTENDED,
    	.load = load_module,
    	.unload = unload_module,
    	.reload = reload_module,
    
    	.load_pri = AST_MODPRI_CHANNEL_DRIVER,
    	.requires = "udptl",