return 0;
}
+ /* if we start gateway we don't need v21 detection sessions any more */
+ destroy_v21_sessions(gateway);
+
/* create the FAX session */
if (!(s = fax_session_new(details, chan, gateway->s, gateway->token))) {
gateway->token = NULL;
}
/*! \pre chan is locked on entry */
-static struct ast_frame *fax_gateway_request_t38(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_frame *f)
+static struct ast_frame *fax_gateway_request_t38(struct fax_gateway *gateway, struct ast_channel *chan)
{
struct ast_frame *fp;
struct ast_control_t38_parameters t38_parameters = {
if (!details) {
ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
ast_framehook_detach(chan, gateway->framehook);
- return f;
+ return NULL;
}
t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
if (!(fp = ast_frisolate(&control_frame))) {
ast_log(LOG_ERROR, "error generating T.38 request control frame on chan %s for T.38 gateway session\n", ast_channel_name(chan));
- return f;
+ return NULL;
}
gateway->t38_state = T38_STATE_NEGOTIATING;
if (gateway->detected_v21) {
enum ast_t38_state state_other;
+ enum ast_t38_state state_active;
+ struct ast_frame *fp;
destroy_v21_sessions(gateway);
ast_channel_unlock(chan);
+ state_active = ast_channel_get_t38_state(active);
state_other = ast_channel_get_t38_state(other);
ast_channel_lock(chan);
- if (state_other == T38_STATE_UNKNOWN) {
- ast_debug(1, "detected v21 preamble from %s\n", ast_channel_name(active));
- return fax_gateway_request_t38(gateway, chan, f);
+
+ ast_debug(1, "detected v21 preamble from %s\n", ast_channel_name(active));
+
+ if (state_active == T38_STATE_UNKNOWN || state_other == T38_STATE_UNKNOWN) {
+ if (!(fp = fax_gateway_request_t38(gateway, chan))) {
+ return f;
+ }
+ /* May be called endpoint is improperly configured to rely on the calling endpoint
+ * to initiate T.38 re-INVITEs, send T.38 negotiation request to called endpoint */
+ if (state_active == T38_STATE_UNKNOWN) {
+ ast_debug(1, "sending T.38 negotiation request to %s\n", ast_channel_name(active));
+ if (active == chan) {
+ ast_channel_unlock(chan);
+ }
+ ast_write(active, fp);
+ if (active == chan) {
+ ast_channel_lock(chan);
+ }
+ }
+ if (state_other == T38_STATE_UNKNOWN) {
+ ast_debug(1, "sending T.38 negotiation request to %s\n", ast_channel_name(other));
+ return fp;
+ }
} else {
- ast_debug(1, "detected v21 preamble on %s, but %s does not support T.38 for T.38 gateway session\n", ast_channel_name(active), ast_channel_name(other));
+ ast_debug(1, "neither %s nor %s support T.38 for T.38 gateway session\n", ast_channel_name(active), ast_channel_name(other));
}
}
ast_channel_lock(chan);
if (state_other == T38_STATE_UNKNOWN) {
gateway->t38_state = T38_STATE_UNAVAILABLE;
- } else {
+ } else if (state_other != T38_STATE_NEGOTIATING) {
ast_framehook_detach(chan, details->gateway_id);
details->gateway_id = -1;