From 08881d6b6412822d5035f63a0775ca1f213c8668 Mon Sep 17 00:00:00 2001
From: WXL (wul) <wl_5969728@163.com>
Date: 星期一, 20 十月 2025 10:17:22 +0800
Subject: [PATCH] 测试完成
---
src/utils/sipService.js | 136 ++++++++++++++++++++++++++++----------------
1 files changed, 86 insertions(+), 50 deletions(-)
diff --git a/src/utils/sipService.js b/src/utils/sipService.js
index 57209b7..a8ce592 100644
--- a/src/utils/sipService.js
+++ b/src/utils/sipService.js
@@ -7,53 +7,87 @@
this.onStatusChange = null;
this.onCallStatusChange = null;
this.onIncomingCall = null;
+ this.isRegistered = false; // 鏂板娉ㄥ唽鐘舵�佹爣蹇�
+ this.registrationTime = null; // 鏂板娉ㄥ唽鎴愬姛鏃堕棿鎴�
}
init(config) {
try {
- this.updateStatus("connecting", "杩炴帴涓�...");
+ this.updateStatus("connecting", "杩炴帴涓�;...");
this.ua = new JsSIP.UA({
sockets: [new JsSIP.WebSocketInterface(config.wsUrl)],
uri: config.sipUri,
password: config.password,
display_name: config.displayName,
- iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
+ iceServers: [],
register: true,
- session_expires: 180,
- sessionTimersExpires: 300,
- extraHeaders: ["Min-SE: 120"],
+ sessionExpires: 1800,
+ minSessionExpires: 90,
register_expires: 300,
- connection_recovery_min_interval: 2,
- connection_recovery_max_interval: 30,
- pcConfig: {
- iceTransportPolicy: "all",
- rtcpMuxPolicy: "require",
- bundlePolicy: "max-bundle"
- }
});
this.ua.start();
// 浜嬩欢鐩戝惉
- this.ua.on("registered", () => this.updateStatus("registered", "宸叉敞鍐�"));
- this.ua.on("registrationFailed", (e) =>
- this.updateStatus("failed", `娉ㄥ唽澶辫触: ${e.cause}`));
- this.ua.on("disconnected", () =>
- this.updateStatus("disconnected", "杩炴帴鏂紑"));
- this.ua.on("connected", () =>
- this.updateStatus("connecting", "閲嶆柊杩炴帴涓�..."));
- this.ua.on("newRTCSession", (data) =>
- this.handleIncomingCall(data.session));
+ this.ua.on("registered", () => {
+ this.isRegistered = true;
+ this.registrationTime = Date.now(); // 璁板綍娉ㄥ唽鎴愬姛鏃堕棿
+ console.log(this.registrationTime, "娉ㄥ唽鏃堕棿");
+ this.updateStatus("registered", "宸叉敞鍐�");
+ });
+
+ this.ua.on("registrationFailed", (e) => {
+ this.isRegistered = false;
+ this.updateStatus("failed", `娉ㄥ唽澶辫触: ${e.cause}`);
+ });
+
+ this.ua.on("unregistered", () => {
+ this.isRegistered = false;
+ let registrationTime = Date.now(); // 璁板綍娉ㄩ攢鎴愬姛鏃堕棿
+ console.log(registrationTime, "娉ㄩ攢鏃堕棿");
+ this.updateStatus("disconnected", "宸叉敞閿�");
+ });
+ this.ua.on("disconnected", () =>
+ this.updateStatus("disconnected", "杩炴帴鏂紑")
+ );
+ this.ua.on("connected", () =>
+ this.updateStatus("connecting", "閲嶆柊杩炴帴涓�...")
+ );
+ this.ua.on("newRTCSession", (data) =>
+ this.handleIncomingCall(data.session)
+ );
} catch (error) {
this.updateStatus("failed", `鍒濆鍖栧け璐�: ${error.message}`);
console.error("SIP鍒濆鍖栧け璐�:", error);
throw error;
}
}
+ // 鏂板鏂规硶锛氭鏌ユ槸鍚﹀彲浠ュ懠鍙�
+ canMakeCall(minDelay = 2000) {
+ if (!this.isRegistered) {
+ return { canCall: false, reason: "SIP鏈敞鍐岋紝鏃犳硶鍛煎彨" };
+ }
+ const now = Date.now();
+ const timeSinceRegistration = now - this.registrationTime;
+
+ if (timeSinceRegistration < minDelay) {
+ const remaining = minDelay - timeSinceRegistration;
+ return {
+ canCall: false,
+ reason: `娉ㄥ唽鎴愬姛锛岃绛夊緟 ${Math.ceil(remaining / 1000)} 绉掑悗鍐嶅懠鍙玚,
+ };
+ }
+
+ return { canCall: true, reason: "" };
+ }
makeCall(targetNumber) {
+ const { canCall, reason } = this.canMakeCall();
+ if (!canCall) {
+ return Promise.reject(new Error(reason));
+ }
return new Promise((resolve, reject) => {
try {
if (!this.ua) {
@@ -65,16 +99,13 @@
}
const options = {
- sessionTimers: false, // 鏆傛椂绂佺敤浠ュ噺灏戝吋瀹规�ч棶棰�
- extraHeaders: [
- "Min-SE: 120",
- "Accept: application/sdp",
- "Supported: outbound"
- ],
+ sessionTimers: true, // 鍚敤浼氳瘽璁℃椂鍣�
+ sessionTimersExpires: 150,
+ extraHeaders: ["Accept: application/sdp"],
mediaConstraints: { audio: true, video: false },
rtcOfferConstraints: {
offerToReceiveAudio: true,
- offerToReceiveVideo: false
+ offerToReceiveVideo: false,
},
eventHandlers: {
progress: () => this.updateCallStatus("calling", "鍛煎彨涓�..."),
@@ -85,8 +116,8 @@
confirmed: () => {
this.updateCallStatus("connected", "閫氳瘽宸叉帴閫�");
resolve();
- }
- }
+ },
+ },
};
this.currentSession = this.ua.call(
@@ -96,9 +127,8 @@
this.setupPeerConnection(this.currentSession);
this.setupAudio(this.currentSession);
-
} catch (error) {
- this.updateCallStatus("failed", `鍛煎彨澶辫触: ${error.message}`);
+ this.updateCallStatus("failed", `鍛煎彨澶辫触22: ${error.message}`);
reject(error);
}
});
@@ -123,41 +153,44 @@
normalizeSDP(offer) {
let sdp = offer.sdp;
- // 1. 鏍囧噯鍖栬繛鎺ヨ
+ // 鏍囧噯鍖朣DP
sdp = sdp.replace(/c=IN IP4.*\r\n/, "c=IN IP4 0.0.0.0\r\n");
+ sdp = sdp.replace(
+ /m=audio \d+.*\r\n/,
+ "m=audio 9 UDP/TLS/RTP/SAVPF 0 8\r\n"
+ );
- // 2. 鏍囧噯鍖栭煶棰戝獟浣撹
- sdp = sdp.replace(/m=audio \d+.*\r\n/,
- "m=audio 9 UDP/TLS/RTP/SAVPF 0 8\r\n");
+ // 纭繚鍖呭惈鍩烘湰缂栬В鐮佸櫒
+ if (!sdp.includes("PCMU/8000")) sdp += "a=rtpmap:0 PCMU/8000\r\n";
+ if (!sdp.includes("PCMA/8000")) sdp += "a=rtpmap:8 PCMA/8000\r\n";
- // 3. 纭繚鍖呭惈鍩烘湰缂栬В鐮佸櫒
- if (!sdp.includes("PCMU/8000")) {
- sdp += "a=rtpmap:0 PCMU/8000\r\n";
- }
- if (!sdp.includes("PCMA/8000")) {
- sdp += "a=rtpmap:8 PCMA/8000\r\n";
- }
-
- // 4. 娣诲姞蹇呰灞炴��
+ // 娣诲姞蹇呰灞炴��
sdp += "a=rtcp-mux\r\n";
sdp += "a=sendrecv\r\n";
console.log("鏍囧噯鍖栧悗鐨凷DP:", sdp);
return new RTCSessionDescription({
type: offer.type,
- sdp: sdp
+ sdp: sdp,
});
}
handleCallFailure(e, reject) {
+ if (e.response?.status_code === 422) {
+ const serverMinSE = e.response.headers["Min-SE"]?.[0]?.raw || "鏈煡";
+ console.error(`鏈嶅姟鍣ㄨ姹� Min-SE 鈮� ${serverMinSE}锛屽綋鍓嶈缃�: 120`);
+ }
console.error("鍛煎彨澶辫触璇︽儏:", {
cause: e.cause,
message: e.message,
- response: e.response && e.response.status_code
+ response: e.response && {
+ status: e.response.status_code,
+ reason: e.response.reason_phrase,
+ },
});
let errorMessage = "鍛煎彨澶辫触";
- switch(e.cause) {
+ switch (e.cause) {
case "Incompatible SDP":
errorMessage = "濯掍綋鍗忓晢澶辫触锛岃妫�鏌ョ紪瑙g爜鍣ㄩ厤缃�";
break;
@@ -165,11 +198,14 @@
case "606":
errorMessage = "瀵规柟璁惧涓嶆敮鎸佸綋鍓嶅獟浣撻厤缃�";
break;
+ case "422":
+ errorMessage = "浼氳瘽鍙傛暟涓嶆弧瓒虫湇鍔″櫒瑕佹眰";
+ break;
default:
- errorMessage = `鍛煎彨澶辫触: ${e.cause || e.message}`;
+ errorMessage = `鍛煎彨澶辫触3: ${e.cause || e.message}`;
}
- this.updateCallStatus("failed", errorMessage);
+ this.updateCallStatus("failed55", errorMessage);
reject(new Error(errorMessage));
}
--
Gitblit v1.9.3