Newer
Older
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "--- ooh323_call- %s\n", dest);
if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
ast_log(LOG_WARNING, "ooh323_call called on %s, neither down nor "
"reserved\n", ast_channel_name(ast));
return -1;
}
ast_mutex_lock(&p->lock);
ast_set_flag(p, H323_OUTGOING);
if (ast_channel_connected(ast)->id.number.valid && ast_channel_connected(ast)->id.number.str) {
ast_free(p->callerid_num);
p->callerid_num = ast_strdup(ast_channel_connected(ast)->id.number.str);
}
if (ast_channel_connected(ast)->id.name.valid && ast_channel_connected(ast)->id.name.str) {
ast_free(p->callerid_name);
p->callerid_name = ast_strdup(ast_channel_connected(ast)->id.name.str);
} else if (ast_channel_connected(ast)->id.number.valid && ast_channel_connected(ast)->id.number.str) {
ast_free(p->callerid_name);
p->callerid_name = ast_strdup(ast_channel_connected(ast)->id.number.str);
ast_channel_connected(ast)->id.name.valid = 1;
ast_free(ast_channel_connected(ast)->id.name.str);
ast_channel_connected(ast)->id.name.str = ast_strdup(gCallerID);
ast_free(p->callerid_name);
p->callerid_name = ast_strdup(ast_channel_connected(ast)->id.name.str);
}
/* Retrieve vars */
if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323ID"))) {
ast_copy_string(p->caller_h323id, val, sizeof(p->caller_h323id));
}
if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323DIALEDDIGITS"))) {
ast_copy_string(p->caller_dialedDigits, val, sizeof(p->caller_dialedDigits));
p->callerid_num = ast_strdup(val);
}
if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323EMAIL"))) {
ast_copy_string(p->caller_email, val, sizeof(p->caller_email));
}
if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323URL"))) {
ast_copy_string(p->caller_url, val, sizeof(p->caller_url));
}
if (p->host && p->port != 0)
snprintf(destination, sizeof(destination), "%s:%d", p->host, p->port);
else if (p->host)
snprintf(destination, sizeof(destination), "%s", p->host);
else
ast_copy_string(destination, dest, sizeof(destination));
destination[sizeof(destination)-1]='\0';
opts.transfercap = ast_channel_transfercapability(ast);
opts.fastStart = p->faststart;
opts.tunneling = p->h245tunneling;
for (i=0;i<480 && !isRunning(p->callToken);i++) usleep(12000);
if(OO_TESTFLAG(p->flags, H323_DISABLEGK)) {
res = ooRunCall(destination, p->callToken, AST_MAX_EXTENSION, &opts);
} else {
res = ooRunCall(destination, p->callToken, AST_MAX_EXTENSION, NULL);
}
ast_mutex_unlock(&p->lock);
if (res != OO_OK) {
ast_log(LOG_ERROR, "Failed to make call\n");
}
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "+++ ooh323_call\n");
return 0;
}
static int ooh323_hangup(struct ast_channel *ast)
{
struct ooh323_pvt *p = ast_channel_tech_pvt(ast);
int q931cause = AST_CAUSE_NORMAL_CLEARING;
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "--- ooh323_hangup\n");
if (p) {
ast_mutex_lock(&p->lock);
if (ast_channel_hangupcause(ast)) {
q931cause = ast_channel_hangupcause(ast);
} else {
const char *cause = pbx_builtin_getvar_helper(ast, "DIALSTATUS");
if (cause) {
if (!strcmp(cause, "CONGESTION")) {
q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
} else if (!strcmp(cause, "BUSY")) {
q931cause = AST_CAUSE_USER_BUSY;
} else if (!strcmp(cause, "CHANISUNVAIL")) {
q931cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
} else if (!strcmp(cause, "NOANSWER")) {
q931cause = AST_CAUSE_NO_ANSWER;
} else if (!strcmp(cause, "CANCEL")) {
q931cause = AST_CAUSE_CALL_REJECTED;
}
}
}
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, " hanging %s with cause: %d\n", p->username, q931cause);
ast_channel_tech_pvt_set(ast, NULL);
if (!ast_test_flag(p, H323_ALREADYGONE)) {
ooh323_convert_hangupcause_asteriskToH323(q931cause), q931cause);
ast_set_flag(p, H323_ALREADYGONE);
/* ast_mutex_unlock(&p->lock); */
ast_set_flag(p, H323_NEEDDESTROY);
/* detach channel here */
if (p->owner) {
ast_channel_tech_pvt_set(p->owner, NULL);
p->owner = NULL;
}
ast_mutex_unlock(&p->lock);
ast_mutex_lock(&usecnt_lock);
usecnt--;
ast_mutex_unlock(&usecnt_lock);
/* Notify the module monitors that use count for resource has changed */
ast_update_use_count();
} else {
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "+++ ooh323_hangup\n");
return 0;
}
static int ooh323_answer(struct ast_channel *ast)
{
struct ooh323_pvt *p = ast_channel_tech_pvt(ast);
char *callToken = (char *)NULL;
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "--- ooh323_answer\n");
if (p) {
ast_mutex_lock(&p->lock);
callToken = (p->callToken ? ast_strdup(p->callToken) : NULL);
if (ast_channel_state(ast) != AST_STATE_UP) {
if (!p->alertsent) {
if (gH323Debug) {
ast_debug(1, "Sending forced ringback for %s, res = %u\n",
callToken, ooManualRingback(callToken));
} else {
ooManualRingback(callToken);
}
p->alertsent = 1;
}
ast_setstate(ast, AST_STATE_UP);
ast_debug(1, "ooh323_answer(%s)\n", ast_channel_name(ast));
ast_channel_unlock(ast);
ooAnswerCall(p->callToken);
}
ast_free(callToken);
}
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "+++ ooh323_answer\n");
return 0;
}
static struct ast_frame *ooh323_read(struct ast_channel *ast)
{
struct ast_frame *fr;
static struct ast_frame null_frame = { AST_FRAME_NULL, };
struct ooh323_pvt *p = ast_channel_tech_pvt(ast);
if (!p) return &null_frame;
ast_mutex_lock(&p->lock);
if (p->rtp)
fr = ooh323_rtp_read(ast, p);
else
fr = &null_frame;
/* time(&p->lastrtprx); */
ast_mutex_unlock(&p->lock);
return fr;
}
static int ooh323_write(struct ast_channel *ast, struct ast_frame *f)
{
struct ooh323_pvt *p = ast_channel_tech_pvt(ast);
int res = 0;
if (p) {
ast_mutex_lock(&p->lock);
p->lastrtptx = time(NULL);
if (f->frametype == AST_FRAME_MODEM) {
ast_debug(1, "Send UDPTL %u/%d len %d for %s\n",
f->frametype, f->subclass.integer, f->datalen, ast_channel_name(ast));
if (p->udptl)
res = ast_udptl_write(p->udptl, f);
ast_mutex_unlock(&p->lock);
return res;
}
if (f->frametype == AST_FRAME_VOICE) {
/* sending progress for first */
if (!ast_test_flag(p, H323_OUTGOING) && !p->progsent &&
ooManualProgress(p->callToken);
p->progsent = 1;
}
if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
if (ast_format_cap_count(ast_channel_nativeformats(ast))) {
Alexander Traud
committed
struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
ast_log(LOG_WARNING,
"Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
ast_format_get_name(f->subclass.format),
ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf),
ast_format_get_name(ast_channel_readformat(ast)),
ast_format_get_name(ast_channel_writeformat(ast)));
ast_set_write_format(ast, f->subclass.format);
} else {
/* ast_set_write_format(ast, f->subclass);
ast->nativeformats = f->subclass; */
}
ast_mutex_unlock(&p->lock);
return 0;
}
if (p->rtp)
res = ast_rtp_instance_write(p->rtp, f);
ast_mutex_unlock(&p->lock);
} else if (f->frametype == AST_FRAME_IMAGE) {
ast_mutex_unlock(&p->lock);
ast_log(LOG_WARNING, "Can't send %u type frames with OOH323 write\n",
f->frametype);
ast_mutex_unlock(&p->lock);
return 0;
}
}
return res;
}
static int ooh323_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
{
struct ooh323_pvt *p = (struct ooh323_pvt *) ast_channel_tech_pvt(ast);
char *callToken = (char *)NULL;
int res = -1, rres;
ast_mutex_lock(&p->lock);
callToken = (p->callToken ? ast_strdup(p->callToken) : NULL);
ast_mutex_unlock(&p->lock);
if (!callToken) {
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, " ooh323_indicate - No callToken\n");
return -1;
}
if (!ast_sockaddr_isnull(&p->redirip)) {
res = 0;
}
if (gH323Debug) {
Tilghman Lesher
committed
ast_verb(0, "----- ooh323_indicate %d on call %s\n", condition, callToken);
switch (condition) {
case AST_CONTROL_INCOMPLETE:
/* While h323 does support overlapped dialing, this channel driver does not
* at this time. Treat a response of Incomplete as if it were congestion.
*/
case AST_CONTROL_CONGESTION:
if (!ast_test_flag(p, H323_ALREADYGONE)) {
ooHangCall(callToken, OO_REASON_LOCAL_CONGESTED, AST_CAUSE_SWITCH_CONGESTION);
}
break;
case AST_CONTROL_BUSY:
if (!ast_test_flag(p, H323_ALREADYGONE)) {
ooHangCall(callToken, OO_REASON_LOCAL_BUSY, AST_CAUSE_USER_BUSY);
}
break;
case AST_CONTROL_HOLD:
ast_moh_start(ast, data, NULL);
break;
case AST_CONTROL_UNHOLD:
ast_moh_stop(ast);
break;
case AST_CONTROL_PROGRESS:
if (ast_channel_state(ast) != AST_STATE_UP) {
rres = ooManualProgress(callToken);
ast_debug(1, "Sending manual progress for %s, res = %u\n", callToken, rres);
}
break;
case AST_CONTROL_RINGING:
if (ast_channel_state(ast) == AST_STATE_RING || ast_channel_state(ast) == AST_STATE_RINGING) {
rres = ooManualRingback(callToken);
ast_debug(1, "Sending manual ringback for %s, res = %u\n", callToken, rres);
}
case AST_CONTROL_SRCUPDATE:
if (p->rtp) {
ast_rtp_instance_update_source(p->rtp);
}
break;
case AST_CONTROL_SRCCHANGE:
if (p->rtp) {
ast_rtp_instance_change_source(p->rtp);
}
if (!ast_channel_connected(ast)->id.name.valid
|| ast_strlen_zero(ast_channel_connected(ast)->id.name.str)) {
if (gH323Debug) {
ast_debug(1, "Sending connected line info for %s (%s)\n",
callToken, ast_channel_connected(ast)->id.name.str);
ooSetANI(callToken, ast_channel_connected(ast)->id.name.str);
Alexandr Anikin
committed
break;
case AST_CONTROL_T38_PARAMETERS:
if (p->t38support != T38_ENABLED) {
struct ast_control_t38_parameters parameters = { .request_response = 0 };
parameters.request_response = AST_T38_REFUSED;
ast_queue_control_data(ast, AST_CONTROL_T38_PARAMETERS,
¶meters, sizeof(parameters));
break;
}
if (datalen != sizeof(struct ast_control_t38_parameters)) {
ast_log(LOG_ERROR, "Invalid datalen for AST_CONTROL_T38. "
"Expected %d, got %d\n",
(int)sizeof(enum ast_control_t38), (int)datalen);
} else {
const struct ast_control_t38_parameters *parameters = data;
struct ast_control_t38_parameters our_parameters;
enum ast_control_t38 message = parameters->request_response;
switch (message) {
case AST_T38_NEGOTIATED:
if (p->faxmode) {
res = 0;
break;
}
case AST_T38_REQUEST_NEGOTIATE:
if (p->faxmode) {
/* T.38 already negotiated */
our_parameters.request_response = AST_T38_NEGOTIATED;
our_parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
our_parameters.rate = AST_T38_RATE_14400;
ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters));
} else if (!p->chmodepend) {
ooRequestChangeMode(p->callToken, 1);
}
break;
case AST_T38_REQUEST_TERMINATE:
if (!p->faxmode) {
/* T.38 already terminated */
our_parameters.request_response = AST_T38_TERMINATED;
ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters));
} else if (!p->chmodepend) {
ooRequestChangeMode(p->callToken, 0);
case AST_T38_REQUEST_PARMS:
our_parameters.request_response = AST_T38_REQUEST_PARMS;
our_parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
our_parameters.rate = AST_T38_RATE_14400;
ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters));
res = AST_T38_REQUEST_PARMS;
break;
default:
;
}
}
break;
case AST_CONTROL_PROCEEDING:
case AST_CONTROL_PVT_CAUSE_CODE:
case AST_CONTROL_MASQUERADE_NOTIFY:
case -1:
break;
default:
ast_log(LOG_WARNING, "Don't know how to indicate condition %d on %s\n",
condition, callToken);
}
ast_mutex_unlock(&p->lock);
if (gH323Debug) {
ast_verb(0, "++++ ooh323_indicate %d on %s is %d\n", condition, callToken, res);
}
ast_free(callToken);
}
static int ooh323_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
{
struct ooh323_pvt *p = (struct ooh323_pvt *) ast_channel_tech_pvt(ast);
int res = -1;
enum ast_t38_state state = T38_STATE_UNAVAILABLE;
char* cp;
if (!p) return -1;
ast_mutex_lock(&p->lock);
if (gH323Debug)
ast_verb(0, "----- ooh323_queryoption %d on channel %s\n", option, ast_channel_name(ast));
switch (option) {
case AST_OPTION_T38_STATE:
if (*datalen != sizeof(enum ast_t38_state)) {
ast_log(LOG_ERROR, "Invalid datalen for AST_OPTION_T38_STATE option."
" Expected %d, got %d\n", (int)sizeof(enum ast_t38_state), *datalen);
break;
}
if (p->t38support != T38_DISABLED) {
if (p->faxmode) {
state = (p->chmodepend) ? T38_STATE_NEGOTIATING : T38_STATE_NEGOTIATED;
} else {
state = T38_STATE_UNKNOWN;
}
}
*((enum ast_t38_state *) data) = state;
res = 0;
break;
case AST_OPTION_DIGIT_DETECT:
cp = (char *) data;
*cp = p->vad ? 1 : 0;
ast_debug(1, "Reporting digit detection %sabled on %s\n",
*cp ? "en" : "dis", ast_channel_name(ast));
res = 0;
break;
default: ;
}
if (gH323Debug)
ast_verb(0, "+++++ ooh323_queryoption %d on channel %s\n", option, ast_channel_name(ast));
return res;
}
static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
{
struct ooh323_pvt *p = ast_channel_tech_pvt(newchan);
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "--- ooh323c ooh323_fixup\n");
ast_mutex_lock(&p->lock);
if (p->owner != oldchan) {
ast_log(LOG_WARNING, "Old channel wasn't %p but was %p\n", oldchan, p->owner);
ast_mutex_unlock(&p->lock);
return -1;
}
if (p->owner == oldchan) {
p->owner = newchan;
} else {
p->owner = oldchan;
}
ast_mutex_unlock(&p->lock);
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "+++ ooh323c ooh323_fixup \n");
return 0;
}
void ooh323_set_write_format(ooCallData *call, struct ast_format *fmt, int txframes)
{
struct ooh323_pvt *p = NULL;
ast_verb(0, "--- ooh323_update_writeformat %s/%d\n",
ast_format_get_name(fmt), txframes);
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);
ao2_replace(p->writeformat, fmt);
if (p->owner) {
struct ast_format_cap *caps;
caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!caps) {
ast_log(LOG_ERROR, "Could not allocate capabilities structure\n");
return;
}
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");
ao2_ref(caps, -1);
if (gH323Debug) {
Alexander Traud
committed
struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
ast_verb(0, "Writeformat before update %s/%s\n",
ast_format_get_name(ast_channel_writeformat(p->owner)),
ast_format_cap_get_names(ast_channel_nativeformats(p->owner), &codec_buf));
}
if (p->dtmfmode & H323_DTMF_RFC2833 && p->dtmfcodec) {
ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
p->rtp, p->dtmfcodec, "audio", "telephone-event", 0);
}
if (p->dtmfmode & H323_DTMF_CISCO && p->dtmfcodec) {
ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
p->rtp, p->dtmfcodec, "audio", "cisco-telephone-event", 0);
}
if (txframes) {
ast_format_cap_set_framing(caps, txframes);
}
ast_format_cap_append(caps, fmt, 0);
ast_channel_nativeformats_set(p->owner, caps);
ao2_ref(caps, -1);
ast_set_write_format(p->owner, ast_channel_writeformat(p->owner));
ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
ast_channel_unlock(p->owner);
} else
ast_log(LOG_ERROR, "No owner found\n");
Tilghman Lesher
committed
ast_verb(0, "+++ ooh323_update_writeformat\n");
void ooh323_set_read_format(ooCallData *call, struct ast_format *fmt)
{
struct ooh323_pvt *p = NULL;
ast_verb(0, "--- ooh323_update_readformat %s\n",
ast_format_get_name(fmt));
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);
ao2_replace(p->readformat, fmt);
struct ast_format_cap *caps;
caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!caps) {
ast_log(LOG_ERROR, "Could not allocate capabilities structure\n");
return;
}
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");
ao2_ref(caps, -1);
if (gH323Debug) {
ast_verb(0, "Readformat before update %s\n",
ast_format_get_name(ast_channel_readformat(p->owner)));
}
ast_format_cap_append(caps, fmt, 0);
ast_channel_nativeformats_set(p->owner, caps);
ao2_ref(caps, -1);
ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
ast_log(LOG_ERROR, "No owner found\n");
ast_mutex_unlock(&p->lock);
Tilghman Lesher
committed
ast_verb(0, "+++ ooh323_update_readformat\n");
}
int onAlerting(ooCallData *call)
{
struct ooh323_pvt *p = NULL;
struct ast_channel *c = NULL;
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "--- onAlerting %s\n", call->callToken);
ast_log(LOG_ERROR, "No matching call found\n");
return -1;
ast_mutex_lock(&p->lock);
ast_mutex_unlock(&p->lock);
ast_debug(1, "Channel has no owner\n");
return 0;
}
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 0;
if (call->remoteDisplayName) {
struct ast_party_connected_line connected;
struct ast_set_party_connected_line update_connected;
memset(&update_connected, 0, sizeof(update_connected));
update_connected.id.name = 1;
ast_party_connected_line_init(&connected);
connected.id.name.valid = 1;
connected.id.name.str = (char *) call->remoteDisplayName;
connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
ast_channel_queue_connected_line_update(c, &connected, &update_connected);
if (ast_channel_state(c) != AST_STATE_UP)
ast_setstate(c, AST_STATE_RINGING);
ast_queue_control(c, AST_CONTROL_RINGING);
ast_channel_unlock(c);
ast_mutex_unlock(&p->lock);
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "+++ onAlerting %s\n", call->callToken);
return OO_OK;
}
int onProgress(ooCallData *call)
{
struct ooh323_pvt *p = NULL;
struct ast_channel *c = NULL;
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "--- onProgress %s\n", call->callToken);
ast_log(LOG_ERROR, "No matching call found\n");
return -1;
ast_mutex_lock(&p->lock);
if (!p->owner) {
ast_mutex_unlock(&p->lock);
ast_log(LOG_ERROR, "Channel has no owner\n");
return 0;
}
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 0;
}
c = p->owner;
if (call->remoteDisplayName) {
struct ast_party_connected_line connected;
struct ast_set_party_connected_line update_connected;
memset(&update_connected, 0, sizeof(update_connected));
update_connected.id.name = 1;
ast_party_connected_line_init(&connected);
connected.id.name.valid = 1;
connected.id.name.str = (char *) call->remoteDisplayName;
connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
ast_channel_queue_connected_line_update(c, &connected, &update_connected);
if (ast_channel_state(c) != AST_STATE_UP)
ast_setstate(c, AST_STATE_RINGING);
ast_queue_control(c, AST_CONTROL_PROGRESS);
ast_channel_unlock(c);
ast_mutex_unlock(&p->lock);
Tilghman Lesher
committed
ast_verb(0, "+++ onProgress %s\n", call->callToken);
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
/**
* Callback for sending digits from H.323 up to asterisk
*
*/
int ooh323_onReceivedDigit(OOH323CallData *call, const char *digit)
{
struct ooh323_pvt *p = NULL;
struct ast_frame f;
int res;
ast_debug(1, "Received Digit: %c\n", digit[0]);
p = find_call(call);
if (!p) {
ast_log(LOG_ERROR, "Failed to find a matching call.\n");
return -1;
}
if (!p->owner) {
ast_log(LOG_ERROR, "Channel has no owner\n");
return -1;
}
ast_mutex_lock(&p->lock);
memset(&f, 0, sizeof(f));
f.frametype = AST_FRAME_DTMF;
f.subclass.integer = digit[0];
f.datalen = 0;
f.samples = 800;
f.offset = 0;
f.data.ptr = NULL;
f.mallocd = 0;
f.src = "SEND_DIGIT";
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 0;
}
res = ast_queue_frame(p->owner, &f);
ast_channel_unlock(p->owner);
ast_mutex_unlock(&p->lock);
return res;
}
int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg)
{
struct ooh323_pvt *p = NULL;
struct ooh323_user *user = NULL;
ooAliases *alias = NULL;
char *at = NULL;
char number [OO_MAX_NUMBER_LENGTH];
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "--- ooh323_onReceivedSetup %s\n", call->callToken);
if (!(p = ooh323_alloc(call->callReference, call->callToken))) {
ast_log(LOG_ERROR, "Failed to create a new call.\n");
return -1;
}
ast_mutex_lock(&p->lock);
ast_clear_flag(p, H323_OUTGOING);
if (call->remoteDisplayName) {
p->callerid_name = ast_strdup(call->remoteDisplayName);
}
if (ooCallGetCallingPartyNumber(call, number, OO_MAX_NUMBER_LENGTH) == OO_OK) {
p->callerid_num = ast_strdup(number);
}
if (call->remoteAliases) {
for (alias = call->remoteAliases; alias; alias = alias->next) {
if (alias->type == T_H225AliasAddress_h323_ID) {
if (!p->callerid_name) {
p->callerid_name = ast_strdup(alias->value);
}
ast_copy_string(p->caller_h323id, alias->value, sizeof(p->caller_h323id));
}
else if(alias->type == T_H225AliasAddress_dialedDigits)
{
if(!p->callerid_num)
p->callerid_num = ast_strdup(alias->value);
ast_copy_string(p->caller_dialedDigits, alias->value,
sizeof(p->caller_dialedDigits));
}
else if(alias->type == T_H225AliasAddress_email_ID)
{
ast_copy_string(p->caller_email, alias->value, sizeof(p->caller_email));
}
else if(alias->type == T_H225AliasAddress_url_ID)
{
ast_copy_string(p->caller_url, alias->value, sizeof(p->caller_url));
}
}
}
number[0] = '\0';
if(ooCallGetCalledPartyNumber(call, number, OO_MAX_NUMBER_LENGTH)== OO_OK) {
ast_copy_string(p->exten, number, sizeof(p->exten));
update_our_aliases(call, p);
if (!ast_strlen_zero(p->callee_dialedDigits)) {
ast_copy_string(p->exten, p->callee_dialedDigits, sizeof(p->exten));
} else if(!ast_strlen_zero(p->callee_h323id)) {
ast_copy_string(p->exten, p->callee_h323id, sizeof(p->exten));
} else if(!ast_strlen_zero(p->callee_email)) {
ast_copy_string(p->exten, p->callee_email, sizeof(p->exten));
if ((at = strchr(p->exten, '@'))) {
*at = '\0';
}
}
}
/* if no extension found, set to default 's' */
if (ast_strlen_zero(p->exten)) {
p->exten[0]='s';
p->exten[1]='\0';
}
user = find_user(p->callerid_name, call->remoteIP);
if(user && (user->incominglimit == 0 || user->inUse < user->incominglimit)) {
ast_mutex_lock(&user->lock);
p->username = ast_strdup(user->name);
p->neighbor.user = user->mUseIP ? ast_strdup(user->mIP) :
ast_strdup(user->name);
ast_copy_string(p->context, user->context, sizeof(p->context));
ast_copy_string(p->accountcode, user->accountcode, sizeof(p->accountcode));
p->amaflags = user->amaflags;
ast_format_cap_append_from_cap(p->cap, user->cap, AST_MEDIA_TYPE_UNKNOWN);
p->g729onlyA = user->g729onlyA;
p->dtmfmode |= user->dtmfmode;
p->dtmfcodec = user->dtmfcodec;
p->faxdetect = user->faxdetect;
p->t38support = user->t38support;
p->rtptimeout = user->rtptimeout;
p->nat = user->nat;
p->h245tunneling = user->h245tunneling;
p->faststart = user->faststart;
p->directrtp = user->directrtp;
p->earlydirect = user->earlydirect;
if (p->faststart)
OO_SETFLAG(call->flags, OO_M_FASTSTART);
else
OO_CLRFLAG(call->flags, OO_M_FASTSTART);
/* if we disable h245tun for this user then we clear flag */
/* in any other case we don't must touch this */
/* ie if we receive setup without h245tun but enabled
we can't enable it per call */
if (!p->h245tunneling)
OO_CLRFLAG(call->flags, OO_M_TUNNELING);
if (user->rtpmask && user->rtpmaskstr[0]) {
p->rtpmask = user->rtpmask;
ast_copy_string(p->rtpmaskstr, user->rtpmaskstr,
if (user->rtdrcount > 0 && user->rtdrinterval > 0) {
p->rtdrcount = user->rtdrcount;
p->rtdrinterval = user->rtdrinterval;
}
Alexandr Anikin
committed
p->aniasdni = user->aniasdni;
if (user->incominglimit) user->inUse++;
ast_mutex_unlock(&user->lock);
} else {
if (!OO_TESTFLAG(p->flags,H323_DISABLEGK)) {
p->username = ast_strdup(call->remoteIP);
p->directrtp = gDirectRTP;
p->earlydirect = gEarlyDirect;
} else {
ast_mutex_unlock(&p->lock);
ast_log(LOG_ERROR, "Unacceptable ip %s\n", call->remoteIP);
ooHangCall(call->callToken, ooh323_convert_hangupcause_asteriskToH323(AST_CAUSE_CALL_REJECTED), AST_CAUSE_CALL_REJECTED);
call->callEndReason = OO_REASON_REMOTE_REJECTED;
}
else {
ooHangCall(call->callToken, ooh323_convert_hangupcause_asteriskToH323(AST_CAUSE_NORMAL_CIRCUIT_CONGESTION), AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
call->callEndReason = OO_REASON_REMOTE_REJECTED;
}
ast_set_flag(p, H323_NEEDDESTROY);
return -1;
}
}
ooh323c_set_capability_for_call(call, p->cap, p->dtmfmode, p->dtmfcodec,
p->t38support, p->g729onlyA);
c = ooh323_new(p, AST_STATE_RING, p->username, 0, NULL, NULL);
if(!c) {
ast_mutex_unlock(&p->lock);
ast_log(LOG_ERROR, "Could not create ast_channel\n");
return -1;
Alexandr Anikin
committed
if (p->aniasdni) {
ooCallSetCallerId(call, p->exten);
}
if (!configure_local_rtp(p, call)) {
ast_mutex_unlock(&p->lock);