UNPKG

sip.js

Version:

A SIP library for JavaScript

109 lines (108 loc) 5.31 kB
import { C } from "../messages/methods/constants.js"; import { InviteClientTransaction } from "../transactions/invite-client-transaction.js"; import { UserAgentClient } from "./user-agent-client.js"; /** * Re-INVITE UAC. * @remarks * 14 Modifying an Existing Session * https://tools.ietf.org/html/rfc3261#section-14 * 14.1 UAC Behavior * https://tools.ietf.org/html/rfc3261#section-14.1 * @public */ export class ReInviteUserAgentClient extends UserAgentClient { constructor(dialog, delegate, options) { const message = dialog.createOutgoingRequestMessage(C.INVITE, options); super(InviteClientTransaction, dialog.userAgentCore, message, delegate); this.delegate = delegate; dialog.signalingStateTransition(message); // FIXME: TODO: next line obviously needs to be improved... dialog.reinviteUserAgentClient = this; // let the dialog know re-invite request sent this.dialog = dialog; } receiveResponse(message) { if (!this.authenticationGuard(message, this.dialog)) { return; } const statusCode = message.statusCode ? message.statusCode.toString() : ""; if (!statusCode) { throw new Error("Response status code undefined."); } switch (true) { case /^100$/.test(statusCode): if (this.delegate && this.delegate.onTrying) { this.delegate.onTrying({ message }); } break; case /^1[0-9]{2}$/.test(statusCode): if (this.delegate && this.delegate.onProgress) { this.delegate.onProgress({ message, session: this.dialog, // eslint-disable-next-line @typescript-eslint/no-unused-vars prack: (options) => { throw new Error("Unimplemented."); } }); } break; case /^2[0-9]{2}$/.test(statusCode): // Update dialog signaling state with offer/answer in body this.dialog.signalingStateTransition(message); if (this.delegate && this.delegate.onAccept) { this.delegate.onAccept({ message, session: this.dialog, ack: (options) => { const outgoingAckRequest = this.dialog.ack(options); return outgoingAckRequest; } }); } break; case /^3[0-9]{2}$/.test(statusCode): this.dialog.signalingStateRollback(); this.dialog.reinviteUserAgentClient = undefined; // ACK was handled by transaction if (this.delegate && this.delegate.onRedirect) { this.delegate.onRedirect({ message }); } break; case /^[4-6][0-9]{2}$/.test(statusCode): this.dialog.signalingStateRollback(); this.dialog.reinviteUserAgentClient = undefined; // ACK was handled by transaction if (this.delegate && this.delegate.onReject) { this.delegate.onReject({ message }); } else { // If a UA receives a non-2xx final response to a re-INVITE, the session // parameters MUST remain unchanged, as if no re-INVITE had been issued. // Note that, as stated in Section 12.2.1.2, if the non-2xx final // response is a 481 (Call/Transaction Does Not Exist), or a 408 // (Request Timeout), or no response at all is received for the re- // INVITE (that is, a timeout is returned by the INVITE client // transaction), the UAC will terminate the dialog. // // If a UAC receives a 491 response to a re-INVITE, it SHOULD start a // timer with a value T chosen as follows: // // 1. If the UAC is the owner of the Call-ID of the dialog ID // (meaning it generated the value), T has a randomly chosen value // between 2.1 and 4 seconds in units of 10 ms. // // 2. If the UAC is not the owner of the Call-ID of the dialog ID, T // has a randomly chosen value of between 0 and 2 seconds in units // of 10 ms. // // When the timer fires, the UAC SHOULD attempt the re-INVITE once more, // if it still desires for that session modification to take place. For // example, if the call was already hung up with a BYE, the re-INVITE // would not take place. // https://tools.ietf.org/html/rfc3261#section-14.1 // FIXME: TODO: The above. } break; default: throw new Error(`Invalid status code ${statusCode}`); } } }