mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2026-01-25 02:07:56 +00:00
freeswitch capture sip error and propagate the same error (#1489)
* fix: propagate SIP 488 error to SBC on endpoint allocation failure When FreeSWITCH returns a SIP 488 'Not Acceptable Here' error during endpoint allocation (e.g., codec incompatibility), this error was not being propagated back to the SBC/client. Instead, the call would wait indefinitely for websocket commands or return a generic 603 response. Implementation: - In _evalEndpointPrecondition(), detect SipError by checking err.type === 'SipError' or err.name === 'SipError' - Extract the SIP status code (e.g., 488), reason, and the Reason header from the error response (e.g., Q.850;cause=88;text=INCOMPATIBLE_DESTINATION) - Send the SIP error response immediately to the SBC with: - X-Reason header: endpoint allocation failure details - Reason header: original Q.850 cause from FreeSWITCH - Notify call status change as Failed with proper SIP status - Release the call immediately instead of waiting for commands Also added fallback handling in InboundCallSession._onTasksDone() to propagate the stored error if immediate send was not possible. * wip * Simplify SipError check to only use err.name
This commit is contained in:
@@ -2500,6 +2500,36 @@ Duration=${duration} `
|
||||
}
|
||||
else {
|
||||
this.logger.error(err, `Error attempting to allocate endpoint for for task ${task.name}`);
|
||||
// Check for SipError type (e.g., 488 codec incompatibility)
|
||||
const isSipError = err.name === 'SipError';
|
||||
if (isSipError && err.status) {
|
||||
// Extract Reason header from SIP response if available (e.g., Q.850;cause=88;text="INCOMPATIBLE_DESTINATION")
|
||||
const sipReasonHeader = err.res?.msg?.headers?.reason;
|
||||
this._endpointAllocationError = {
|
||||
status: err.status,
|
||||
reason: err.reason || 'Endpoint Allocation Failed',
|
||||
sipReasonHeader
|
||||
};
|
||||
this.logger.info({endpointAllocationError: this._endpointAllocationError},
|
||||
'Captured SipError for propagation to SBC');
|
||||
|
||||
// Send SIP error response immediately for inbound calls
|
||||
if (this.res && !this.res.finalResponseSent) {
|
||||
this.logger.info(`Sending ${err.status} response to SBC due to SipError`);
|
||||
this.res.send(err.status, {
|
||||
headers: {
|
||||
'X-Reason': `endpoint allocation failure: ${err.reason || 'Endpoint Allocation Failed'}`,
|
||||
...(sipReasonHeader && {'Reason': sipReasonHeader})
|
||||
}
|
||||
});
|
||||
this._notifyCallStatusChange({
|
||||
callStatus: CallStatus.Failed,
|
||||
sipStatus: err.status,
|
||||
sipReason: err.reason || 'Endpoint Allocation Failed'
|
||||
});
|
||||
this._callReleased();
|
||||
}
|
||||
}
|
||||
throw new Error(`${BADPRECONDITIONS}: unable to allocate endpoint`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,19 @@ class InboundCallSession extends CallSession {
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (this._endpointAllocationError) {
|
||||
// Propagate SIP error from endpoint allocation failure back to the client
|
||||
const {status, reason, sipReasonHeader} = this._endpointAllocationError;
|
||||
this.rootSpan.setAttributes({'call.termination': `endpoint allocation SIP error ${status}`});
|
||||
this.logger.info({endpointAllocationError: this._endpointAllocationError},
|
||||
`InboundCallSession:_onTasksDone generating ${status} due to endpoint allocation failure`);
|
||||
this.res.send(status, {
|
||||
headers: {
|
||||
'X-Reason': `endpoint allocation failure: ${reason}`,
|
||||
...(sipReasonHeader && {'Reason': sipReasonHeader})
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.rootSpan.setAttributes({'call.termination': 'tasks completed without answering call'});
|
||||
this.logger.info('InboundCallSession:_onTasksDone auto-generating non-success response to invite');
|
||||
|
||||
Reference in New Issue
Block a user