@koi-design/callkit 2.3.0-beta.9 → 2.3.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -45,7 +45,7 @@ var Api = class {
45
45
  const res = await this.post({
46
46
  url: "/auth/agentUser/login",
47
47
  method: "post",
48
- data: params
48
+ data: { ...params, browserVersion: navigator.userAgent }
49
49
  });
50
50
  return res;
51
51
  } finally {
@@ -508,7 +508,11 @@ var SocketReceiveEvent = {
508
508
  ERROR: "ERROR",
509
509
  SESSION_ERROR: "SESSION_ERROR",
510
510
  WAITING_QUEUE: "WAITING_QUEUE",
511
- CUSTOMER_MATCH_BLACK_PHONE: "CUSTOMER_MATCH_BLACK_PHONE"
511
+ CUSTOMER_MATCH_BLACK_PHONE: "CUSTOMER_MATCH_BLACK_PHONE",
512
+ /**
513
+ * Agent RTP loss
514
+ */
515
+ AGENT_RTP_LOSS: "AGENT_RTP_LOSS"
512
516
  };
513
517
  var EncryptionMethod = {
514
518
  NONE: "NONE",
@@ -553,7 +557,9 @@ var SIP_RECONNECT_CONFIG = {
553
557
  delay: 1e3,
554
558
  registererOptions: {
555
559
  refreshFrequency: 90
556
- }
560
+ },
561
+ enableMessageKeepalive: true,
562
+ messageKeepaliveInterval: 30
557
563
  };
558
564
 
559
565
  // core/call.ts
@@ -697,13 +703,13 @@ var Call = class {
697
703
  // package.json
698
704
  var package_default = {
699
705
  name: "@koi-design/callkit",
700
- version: "2.3.0-beta.9",
706
+ version: "2.3.1-beta.2",
701
707
  description: "callkit",
702
708
  author: "koi",
703
709
  license: "ISC",
704
710
  scripts: {
705
711
  build: "tsup",
706
- start: "pnpm build && vite --host 0.0.0.0",
712
+ start: "vite --host 0.0.0.0",
707
713
  dev: "tsup --watch",
708
714
  lint: "eslint -c ../../.eslintrc.js --ext .jsx,.js,.tsx,.ts ./package --fix",
709
715
  release: "tsup && node scripts/pkg.js"
@@ -15538,7 +15544,15 @@ var Connect = class {
15538
15544
  this.callKit = callKit;
15539
15545
  }
15540
15546
  get reconnectConfig() {
15541
- return this.callKit.config.getReconnectConfig("sip");
15547
+ const { userInfo } = this.callKit.config.getConfig();
15548
+ const { enableMessageKeepalive } = userInfo;
15549
+ const { messageKeepaliveInterval } = userInfo;
15550
+ const defaultConfig = this.callKit.config.getReconnectConfig("sip");
15551
+ if (enableMessageKeepalive) {
15552
+ defaultConfig.enableMessageKeepalive = enableMessageKeepalive;
15553
+ defaultConfig.messageKeepaliveInterval = messageKeepaliveInterval;
15554
+ }
15555
+ return defaultConfig;
15542
15556
  }
15543
15557
  // current call id for invite data
15544
15558
  currentCallId = null;
@@ -15662,6 +15676,7 @@ var Connect = class {
15662
15676
  }
15663
15677
  }
15664
15678
  this.setConnectStatus(CallStatus.init);
15679
+ this.stopMessageKeepalive();
15665
15680
  }
15666
15681
  getAduioReference() {
15667
15682
  const { audioRef } = this.callKit.config.getConfig();
@@ -15797,8 +15812,6 @@ var Connect = class {
15797
15812
  });
15798
15813
  return;
15799
15814
  }
15800
- const { userInfo } = this.callKit.config.getConfig();
15801
- const { userPart, fsIp, fsPort } = userInfo;
15802
15815
  const { registererOptions = {} } = this.reconnectConfig;
15803
15816
  this.registerer = new Registerer(this.userAgent, registererOptions);
15804
15817
  this.registerer.stateChange.addListener((state) => {
@@ -15816,6 +15829,7 @@ var Connect = class {
15816
15829
  if (!this.isInCallRefering()) {
15817
15830
  this.setConnectStatus(CallStatus.init);
15818
15831
  }
15832
+ this.stopMessageKeepalive();
15819
15833
  this.callKit.trigger(KitEvent.SIP_REGISTERER_EVENT, {
15820
15834
  registererState: state,
15821
15835
  isRegistered: this.isRegistered()
@@ -15832,27 +15846,26 @@ var Connect = class {
15832
15846
  });
15833
15847
  this.setRegister(true);
15834
15848
  if (this.isReConnected) {
15835
- if (this.currentSession && (this.currentSession.state === SessionState2.Established || this.currentSession.state === SessionState2.Establishing) && this.isCalling()) {
15836
- const selfUri = `sip:manualCallAgent${userPart}@${fsIp}:${fsPort}`;
15849
+ if (this.canReferInCallToSelf()) {
15837
15850
  this.callKit.logger.info(
15838
15851
  "Reconnected, referring active session to self",
15839
15852
  {
15840
15853
  caller: "Connect.setupRegisterer.registererStateChange",
15841
15854
  type: "SIP",
15842
15855
  content: {
15843
- selfUri,
15856
+ selfUri: this.getSelfReferUri(),
15844
15857
  sessionState: this.currentSession.state,
15845
15858
  connectStatus: this.connectStatus
15846
15859
  }
15847
15860
  }
15848
15861
  );
15849
- this.referInCall(selfUri).catch((err) => {
15862
+ this.referInCallToSelf().catch((err) => {
15850
15863
  this.callKit.logger.error(err, {
15851
15864
  caller: "Connect.setupRegisterer.registererStateChange",
15852
15865
  type: "SIP",
15853
15866
  content: {
15854
15867
  errCode: ErrorCode.WEBRTC_CALL_INVITE_ERROR,
15855
- selfUri
15868
+ selfUri: this.getSelfReferUri()
15856
15869
  }
15857
15870
  });
15858
15871
  });
@@ -15873,6 +15886,7 @@ var Connect = class {
15873
15886
  }
15874
15887
  this.setIsReConnected(false);
15875
15888
  }
15889
+ this.startMessageKeepalive();
15876
15890
  this.callKit.trigger(KitEvent.SIP_REGISTERER_EVENT, {
15877
15891
  registererState: state,
15878
15892
  isRegistered: this.isRegistered()
@@ -15892,6 +15906,7 @@ var Connect = class {
15892
15906
  if (!this.isInCallRefering()) {
15893
15907
  this.setConnectStatus(CallStatus.init);
15894
15908
  }
15909
+ this.stopMessageKeepalive();
15895
15910
  this.callKit.trigger(KitEvent.SIP_REGISTERER_EVENT, {
15896
15911
  registererState: state,
15897
15912
  isRegistered: this.isRegistered(),
@@ -15912,6 +15927,7 @@ var Connect = class {
15912
15927
  if (!this.isInCallRefering()) {
15913
15928
  this.setConnectStatus(CallStatus.init);
15914
15929
  }
15930
+ this.stopMessageKeepalive();
15915
15931
  this.callKit.trigger(KitEvent.SIP_REGISTERER_EVENT, {
15916
15932
  registererState: state,
15917
15933
  isRegistered: this.isRegistered(),
@@ -15958,7 +15974,7 @@ var Connect = class {
15958
15974
  this.mediaStream = await navigator.mediaDevices.getUserMedia(constrains);
15959
15975
  return this.mediaStream;
15960
15976
  };
15961
- const { userPart, fsIp, fsPort, iceInfo, wsUrl } = userInfo;
15977
+ const { userPart, fsIp, fsPort, fsPassword, iceInfo, wsUrl } = userInfo;
15962
15978
  const connectConfig = {
15963
15979
  uri: UserAgent.makeURI(`sip:${userPart}@${fsIp}:${fsPort}`),
15964
15980
  displayName: userPart,
@@ -15967,6 +15983,8 @@ var Connect = class {
15967
15983
  traceSip: true
15968
15984
  },
15969
15985
  logLevel: "error",
15986
+ authorizationUsername: userPart,
15987
+ authorizationPassword: fsPassword,
15970
15988
  allowLegacyNotifications: true,
15971
15989
  contactName: userPart,
15972
15990
  contactParams: { transport: "wss" },
@@ -16222,7 +16240,10 @@ var Connect = class {
16222
16240
  }
16223
16241
  });
16224
16242
  this.setupRegisterer();
16225
- await this.registerer.register().catch(async (err) => {
16243
+ try {
16244
+ await this.registerer.register();
16245
+ this.startMessageKeepalive();
16246
+ } catch (err) {
16226
16247
  this.callKit.reset();
16227
16248
  this.callKit.logger.error(err?.message, {
16228
16249
  caller: "Connect.register",
@@ -16231,9 +16252,10 @@ var Connect = class {
16231
16252
  errCode: ErrorCode.WEBRTC_REGISTER_ERROR
16232
16253
  }
16233
16254
  });
16234
- });
16255
+ }
16235
16256
  },
16236
16257
  onDisconnect: (error) => {
16258
+ this.stopMessageKeepalive();
16237
16259
  if (error) {
16238
16260
  this.callKit.logger.warn("SIP User Agent Disconnected with error", {
16239
16261
  caller: "Connect.register",
@@ -16269,6 +16291,7 @@ var Connect = class {
16269
16291
  }
16270
16292
  reconnectTimer;
16271
16293
  reconnectAttempts = 0;
16294
+ messageKeepaliveTimer;
16272
16295
  startReconnectTimer() {
16273
16296
  if (this._isError || this.isReConnected)
16274
16297
  return;
@@ -16322,8 +16345,53 @@ var Connect = class {
16322
16345
  }
16323
16346
  }, this.reconnectConfig.delay);
16324
16347
  }
16348
+ stopMessageKeepalive() {
16349
+ if (this.messageKeepaliveTimer) {
16350
+ clearInterval(this.messageKeepaliveTimer);
16351
+ this.messageKeepaliveTimer = void 0;
16352
+ }
16353
+ }
16354
+ startMessageKeepalive() {
16355
+ const { enableMessageKeepalive, messageKeepaliveInterval } = this.reconnectConfig;
16356
+ if (!enableMessageKeepalive)
16357
+ return;
16358
+ this.stopMessageKeepalive();
16359
+ this.messageKeepaliveTimer = setInterval(() => {
16360
+ this.sendKeepaliveMessage();
16361
+ }, messageKeepaliveInterval * 1e3);
16362
+ }
16363
+ async sendKeepaliveMessage() {
16364
+ try {
16365
+ if (!this.isRegistered() || !this.userAgent)
16366
+ return;
16367
+ const { userInfo } = this.callKit.config.getConfig();
16368
+ const { userPart, fsIp, fsPort } = userInfo || {};
16369
+ const target = UserAgent.makeURI(`sip:${userPart}@${fsIp}:${fsPort}`);
16370
+ if (!target)
16371
+ return;
16372
+ const messager = new Messager(this.userAgent, target, "");
16373
+ await messager.message();
16374
+ this.callKit.logger.info("MESSAGE keepalive ok", {
16375
+ caller: "Connect.sendKeepaliveMessage",
16376
+ type: "SIP",
16377
+ content: {}
16378
+ });
16379
+ } catch (err) {
16380
+ this.callKit.logger.error(err, {
16381
+ caller: "Connect.sendKeepaliveMessage",
16382
+ type: "SIP",
16383
+ content: {}
16384
+ });
16385
+ this.stopMessageKeepalive();
16386
+ this.callKit.trigger(KitEvent.SIP_CONNECT_EVENT, {
16387
+ event: "MESSAGE_KEEPALIVE_FAILED"
16388
+ });
16389
+ this.startReconnectTimer();
16390
+ }
16391
+ }
16325
16392
  async stop() {
16326
16393
  await this.userAgent.stop();
16394
+ this.stopMessageKeepalive();
16327
16395
  }
16328
16396
  async unregister() {
16329
16397
  this.callKit.logger.info("connect unregister", {
@@ -16333,6 +16401,7 @@ var Connect = class {
16333
16401
  isRegistered: this.isRegistered()
16334
16402
  }
16335
16403
  });
16404
+ this.stopMessageKeepalive();
16336
16405
  if (!this.isRegistered() || !this.registerer) {
16337
16406
  this.callKit.logger.warn("No registerer to unregister.", {
16338
16407
  caller: "Connect.unregister",
@@ -16681,6 +16750,199 @@ var Connect = class {
16681
16750
  }
16682
16751
  this.currentSession.refer(target, extra?.sessionReferOptions);
16683
16752
  }
16753
+ /**
16754
+ * Get the SIP URI for "refer to self" (same as reconnection refer logic).
16755
+ * Shared by referInCallToSelf and internal reconnection refer.
16756
+ */
16757
+ getSelfReferUri() {
16758
+ const { userInfo } = this.callKit.config.getConfig();
16759
+ const { userPart, fsIp, fsPort } = userInfo;
16760
+ return `sip:manualCallAgent${userPart}@${fsIp}:${fsPort}`;
16761
+ }
16762
+ /**
16763
+ * Whether we can refer the current call to self (has active session in Established/Establishing and is calling).
16764
+ * Shared by reconnection logic and referInCallToSelf.
16765
+ */
16766
+ canReferInCallToSelf() {
16767
+ return !!this.currentSession && (this.currentSession.state === SessionState2.Established || this.currentSession.state === SessionState2.Establishing) && this.isCalling();
16768
+ }
16769
+ /**
16770
+ * Refer the current call to self (e.g. Agent RTP loss recovery, post-reconnect recovery).
16771
+ * Socket and other callers can use this without constructing referTo.
16772
+ */
16773
+ async referInCallToSelf(callUuid, extra) {
16774
+ if (callUuid && this.currentCallId !== callUuid) {
16775
+ this.callKit.logger.warn(
16776
+ "Cannot refer in call to self: callUuid mismatch",
16777
+ {
16778
+ caller: "Connect.referInCallToSelf",
16779
+ type: "SIP",
16780
+ content: {
16781
+ currentCallId: this.currentCallId,
16782
+ callUuid
16783
+ }
16784
+ }
16785
+ );
16786
+ return;
16787
+ }
16788
+ if (!this.canReferInCallToSelf()) {
16789
+ this.callKit.logger.warn(
16790
+ "Cannot refer in call to self: preconditions not met",
16791
+ {
16792
+ caller: "Connect.referInCallToSelf",
16793
+ type: "SIP",
16794
+ content: {
16795
+ hasCurrentSession: !!this.currentSession,
16796
+ sessionState: this.currentSession?.state,
16797
+ isCalling: this.isCalling()
16798
+ }
16799
+ }
16800
+ );
16801
+ return;
16802
+ }
16803
+ const selfUri = this.getSelfReferUri();
16804
+ return this.referInCall(selfUri, extra);
16805
+ }
16806
+ };
16807
+
16808
+ // core/heartbeat-worker.ts
16809
+ var workerCode = `
16810
+ let timer = null;
16811
+ let interval = 30000;
16812
+
16813
+ self.onmessage = function(e) {
16814
+ const { type, interval: newInterval } = e.data;
16815
+
16816
+ if (type === 'start') {
16817
+ if (timer) {
16818
+ clearInterval(timer);
16819
+ }
16820
+ interval = newInterval || interval;
16821
+ timer = setInterval(() => {
16822
+ self.postMessage({ type: 'tick' });
16823
+ }, interval);
16824
+ }
16825
+
16826
+ if (type === 'stop') {
16827
+ if (timer) {
16828
+ clearInterval(timer);
16829
+ timer = null;
16830
+ }
16831
+ }
16832
+
16833
+ if (type === 'updateInterval') {
16834
+ interval = newInterval;
16835
+ if (timer) {
16836
+ clearInterval(timer);
16837
+ timer = setInterval(() => {
16838
+ self.postMessage({ type: 'tick' });
16839
+ }, interval);
16840
+ }
16841
+ }
16842
+ };
16843
+ `;
16844
+ function createHeartbeatWorker() {
16845
+ try {
16846
+ const blob = new Blob([workerCode], { type: "application/javascript" });
16847
+ const workerUrl = URL.createObjectURL(blob);
16848
+ const worker = new Worker(workerUrl);
16849
+ URL.revokeObjectURL(workerUrl);
16850
+ return worker;
16851
+ } catch {
16852
+ return null;
16853
+ }
16854
+ }
16855
+ var HeartbeatManager = class {
16856
+ worker = null;
16857
+ fallbackTimer = null;
16858
+ interval = 3e4;
16859
+ onTick = null;
16860
+ isRunning = false;
16861
+ constructor() {
16862
+ this.worker = createHeartbeatWorker();
16863
+ if (this.worker) {
16864
+ this.worker.onmessage = (e) => {
16865
+ if (e.data.type === "tick" && this.onTick) {
16866
+ this.onTick();
16867
+ }
16868
+ };
16869
+ }
16870
+ }
16871
+ /**
16872
+ * Start the heartbeat
16873
+ * @param interval - Interval in milliseconds
16874
+ * @param onTick - Callback function to execute on each tick
16875
+ */
16876
+ start(interval, onTick) {
16877
+ this.stop();
16878
+ this.interval = interval;
16879
+ this.onTick = onTick;
16880
+ this.isRunning = true;
16881
+ if (this.worker) {
16882
+ this.worker.postMessage({
16883
+ type: "start",
16884
+ interval
16885
+ });
16886
+ } else {
16887
+ this.fallbackTimer = setInterval(() => {
16888
+ if (this.onTick) {
16889
+ this.onTick();
16890
+ }
16891
+ }, interval);
16892
+ }
16893
+ }
16894
+ /**
16895
+ * Stop the heartbeat
16896
+ */
16897
+ stop() {
16898
+ this.isRunning = false;
16899
+ this.onTick = null;
16900
+ if (this.worker) {
16901
+ this.worker.postMessage({ type: "stop" });
16902
+ }
16903
+ if (this.fallbackTimer) {
16904
+ clearInterval(this.fallbackTimer);
16905
+ this.fallbackTimer = null;
16906
+ }
16907
+ }
16908
+ /**
16909
+ * Update the heartbeat interval
16910
+ * @param interval - New interval in milliseconds
16911
+ */
16912
+ updateInterval(interval) {
16913
+ this.interval = interval;
16914
+ if (!this.isRunning)
16915
+ return;
16916
+ if (this.worker) {
16917
+ this.worker.postMessage({
16918
+ type: "updateInterval",
16919
+ interval
16920
+ });
16921
+ } else if (this.fallbackTimer && this.onTick) {
16922
+ clearInterval(this.fallbackTimer);
16923
+ this.fallbackTimer = setInterval(() => {
16924
+ if (this.onTick) {
16925
+ this.onTick();
16926
+ }
16927
+ }, interval);
16928
+ }
16929
+ }
16930
+ /**
16931
+ * Destroy the heartbeat manager and release resources
16932
+ */
16933
+ destroy() {
16934
+ this.stop();
16935
+ if (this.worker) {
16936
+ this.worker.terminate();
16937
+ this.worker = null;
16938
+ }
16939
+ }
16940
+ /**
16941
+ * Check if using Web Worker
16942
+ */
16943
+ isUsingWorker() {
16944
+ return this.worker !== null;
16945
+ }
16684
16946
  };
16685
16947
 
16686
16948
  // core/socket.ts
@@ -16688,7 +16950,7 @@ var Socket = class {
16688
16950
  callKit;
16689
16951
  ws;
16690
16952
  lastPingTime = void 0;
16691
- pingTimer;
16953
+ heartbeatManager;
16692
16954
  /**
16693
16955
  * @description reconnect timer
16694
16956
  */
@@ -16721,9 +16983,32 @@ var Socket = class {
16721
16983
  }
16722
16984
  constructor(callKit) {
16723
16985
  this.callKit = callKit;
16986
+ this.heartbeatManager = new HeartbeatManager();
16987
+ }
16988
+ get isUserSetPingTryCount() {
16989
+ const { userInfo } = this.callKit.config.getConfig();
16990
+ const { pingTryCount } = userInfo;
16991
+ return Number.isInteger(pingTryCount) && pingTryCount > 0;
16724
16992
  }
16725
16993
  get reconnectConfig() {
16726
- return this.callKit.config.getReconnectConfig("incall");
16994
+ const incallConfig = this.callKit.config.getReconnectConfig("incall");
16995
+ const { userInfo } = this.callKit.config.getConfig();
16996
+ const { pingTryCount, pingTryCountInterval } = userInfo;
16997
+ if (pingTryCount > 0) {
16998
+ return {
16999
+ ...incallConfig,
17000
+ maxAttempts: pingTryCount,
17001
+ interval: pingTryCountInterval * 1e3
17002
+ };
17003
+ }
17004
+ return incallConfig;
17005
+ }
17006
+ get pingInterval() {
17007
+ const { keepaliveInterval } = this.callKit.config.getConfig().userInfo;
17008
+ if (Number.isInteger(keepaliveInterval) && keepaliveInterval > 0) {
17009
+ return keepaliveInterval * 1e3;
17010
+ }
17011
+ return this.reconnectConfig.pingInterval;
16727
17012
  }
16728
17013
  isConnected() {
16729
17014
  return this.connectAuthState.isConnected;
@@ -16748,7 +17033,17 @@ var Socket = class {
16748
17033
  this.setConnectAuthState("isConnected", false);
16749
17034
  const { enabled } = this.reconnectConfig;
16750
17035
  if (!this.callKit.config.isLogin() || !enabled) {
16751
- this.callKit.reset();
17036
+ if (this.callKit.connect.isCalling()) {
17037
+ this.callKit.logger.warn("Disconnect during call, delay reset", {
17038
+ caller: "Socket.handleDisconnect",
17039
+ type: "INCALL",
17040
+ content: {
17041
+ connectStatus: this.callKit.connect.connectStatus
17042
+ }
17043
+ });
17044
+ } else {
17045
+ this.callKit.reset();
17046
+ }
16752
17047
  this.callKit.trigger(KitEvent.INCALL_CONNECT_EVENT, {
16753
17048
  event: "INCALL_NOT_CONNECTED"
16754
17049
  });
@@ -16906,6 +17201,28 @@ var Socket = class {
16906
17201
  this.setConnectAuthState("startConfirm", true);
16907
17202
  this.cleanReconnectState();
16908
17203
  }
17204
+ if (data.event === SocketReceiveEvent.AGENT_RTP_LOSS) {
17205
+ this.callKit.logger.warn("Agent RTP loss", {
17206
+ caller: "Socket.onMessage",
17207
+ type: "INCALL",
17208
+ content: {
17209
+ data: {
17210
+ callUuid,
17211
+ ...content
17212
+ },
17213
+ event: SocketReceiveEvent.AGENT_RTP_LOSS
17214
+ }
17215
+ });
17216
+ if (callUuid) {
17217
+ this.callKit.connect.referInCallToSelf(callUuid).catch((err) => {
17218
+ this.callKit.logger.error(err, {
17219
+ caller: "Socket.onMessage:AGENT_RTP_LOSS",
17220
+ type: "INCALL",
17221
+ content: { callUuid, event: SocketReceiveEvent.AGENT_RTP_LOSS }
17222
+ });
17223
+ });
17224
+ }
17225
+ }
16909
17226
  if (data.event === SocketReceiveEvent.CUSTOMER_RINGING) {
16910
17227
  this.callKit.trigger(KitEvent.CALL_RINGING, {
16911
17228
  time: /* @__PURE__ */ new Date(),
@@ -16954,6 +17271,18 @@ var Socket = class {
16954
17271
  this.send(SocketSendEvent.END, { agentId: userInfo.agentId, callUuid });
16955
17272
  }
16956
17273
  if (data.event === SocketReceiveEvent.ERROR) {
17274
+ if (this.callKit.connect.isCalling()) {
17275
+ this.callKit.logger.warn("socket onMessage error during call, ignore", {
17276
+ caller: "Socket.onMessage",
17277
+ type: "INCALL",
17278
+ content: {
17279
+ errCode: ErrorCode.SOCKET_CONNECT_ERROR,
17280
+ isCalling: this.callKit.connect.isCalling(),
17281
+ data: content
17282
+ }
17283
+ });
17284
+ return;
17285
+ }
16957
17286
  this.setConnectAuthState("isError", true);
16958
17287
  this.callKit.reset();
16959
17288
  this.callKit.logger.error(data.msg, {
@@ -16962,20 +17291,24 @@ var Socket = class {
16962
17291
  content: {
16963
17292
  errCode: ErrorCode.SOKET_SERVER_ERROR,
16964
17293
  data: content,
16965
- callUuid
17294
+ callUuid,
17295
+ delayReset: this.callKit.connect.isCalling()
16966
17296
  }
16967
17297
  });
16968
17298
  }
16969
17299
  if (data.event === SocketReceiveEvent.SESSION_ERROR) {
16970
17300
  this.setConnectAuthState("isError", true);
16971
- this.callKit.reset();
17301
+ if (!this.callKit.connect.isCalling()) {
17302
+ this.callKit.reset();
17303
+ }
16972
17304
  this.callKit.logger.error(data.msg, {
16973
17305
  caller: `Socket.onMessage:${data.event}`,
16974
17306
  type: "INCALL",
16975
17307
  content: {
16976
17308
  data: content,
16977
17309
  event: SocketReceiveEvent.SESSION_ERROR,
16978
- callUuid
17310
+ callUuid,
17311
+ delayReset: this.callKit.connect.isCalling()
16979
17312
  }
16980
17313
  });
16981
17314
  }
@@ -17007,6 +17340,18 @@ var Socket = class {
17007
17340
  this.callKit.trigger(KitEvent.INCALL_CONNECT_EVENT, {
17008
17341
  event: "INCALL_NOT_CONNECTED"
17009
17342
  });
17343
+ if (this.callKit.connect.isCalling()) {
17344
+ this.callKit.logger.warn("socket send during call, ignore", {
17345
+ caller: "Socket.onMessage",
17346
+ type: "INCALL",
17347
+ content: {
17348
+ errCode: ErrorCode.SOCKET_CONNECT_ERROR,
17349
+ isCalling: this.callKit.connect.isCalling(),
17350
+ data: message
17351
+ }
17352
+ });
17353
+ return;
17354
+ }
17010
17355
  this.callKit.reset();
17011
17356
  this.callKit.logger.error("socket not connected", {
17012
17357
  caller: "Socket.send",
@@ -17059,8 +17404,8 @@ var Socket = class {
17059
17404
  return;
17060
17405
  this.send(SocketSendEvent.PING);
17061
17406
  const now = Date.now();
17062
- const { pingInterval, pingTimeout } = this.reconnectConfig;
17063
- if (now - this.lastPingTime > pingInterval + pingTimeout) {
17407
+ const { pingTimeout } = this.reconnectConfig;
17408
+ if (now - this.lastPingTime > this.pingInterval + pingTimeout) {
17064
17409
  this.callKit.logger.warn("Ping timeout not connected", {
17065
17410
  caller: "Socket.ping",
17066
17411
  type: "INCALL",
@@ -17072,26 +17417,48 @@ var Socket = class {
17072
17417
  this.callKit.trigger(KitEvent.INCALL_CONNECT_EVENT, {
17073
17418
  event: "INCALL_PING_TIMEOUT"
17074
17419
  });
17420
+ if (this.isUserSetPingTryCount) {
17421
+ this.handlePingTimeout();
17422
+ }
17075
17423
  }
17076
17424
  }
17425
+ handlePingTimeout() {
17426
+ const { userInfo } = this.callKit.config.getConfig();
17427
+ const { pingTryCount, pingTryCountInterval } = userInfo;
17428
+ this.callKit.logger.warn("Ping timeout, user set ping try count", {
17429
+ caller: "Socket.handlePingTimeout",
17430
+ type: "INCALL",
17431
+ content: {
17432
+ errCode: ErrorCode.SOCKET_PING_TIMEOUT,
17433
+ isUserSetPingTryCount: this.isUserSetPingTryCount,
17434
+ pingTryCount,
17435
+ pingTryCountInterval
17436
+ }
17437
+ });
17438
+ this.attemptReconnect();
17439
+ }
17077
17440
  checkPing() {
17078
- if (this.pingTimer) {
17079
- clearInterval(this.pingTimer);
17080
- }
17081
- const { pingInterval } = this.reconnectConfig;
17082
- this.pingTimer = setInterval(() => {
17441
+ this.heartbeatManager.start(this.pingInterval, () => {
17083
17442
  this.ping();
17084
- }, pingInterval);
17443
+ });
17444
+ this.callKit.logger.info(
17445
+ `Heartbeat started with Worker: ${this.heartbeatManager.isUsingWorker()}`,
17446
+ {
17447
+ caller: "Socket.checkPing",
17448
+ type: "INCALL",
17449
+ content: {
17450
+ pingInterval: this.pingInterval,
17451
+ usingWorker: this.heartbeatManager.isUsingWorker()
17452
+ }
17453
+ }
17454
+ );
17085
17455
  }
17086
17456
  /**
17087
17457
  * reset socket connection and all states
17088
17458
  */
17089
17459
  async reset(config) {
17090
17460
  const { force = false } = config || {};
17091
- if (this.pingTimer) {
17092
- clearInterval(this.pingTimer);
17093
- this.pingTimer = void 0;
17094
- }
17461
+ this.heartbeatManager.stop();
17095
17462
  if (force) {
17096
17463
  this.callKit.trigger(KitEvent.INCALL_CONNECT_EVENT, {
17097
17464
  event: "INCALL_RESET"
@@ -17102,6 +17469,12 @@ var Socket = class {
17102
17469
  this.setConnectAuthState("startConfirm", false);
17103
17470
  this.clearWebSocket();
17104
17471
  }
17472
+ /**
17473
+ * Destroy the heartbeat manager
17474
+ */
17475
+ destroyHeartbeat() {
17476
+ this.heartbeatManager.destroy();
17477
+ }
17105
17478
  attemptReconnect() {
17106
17479
  if (this.reconnectTimer) {
17107
17480
  clearTimeout(this.reconnectTimer);
@@ -17109,19 +17482,40 @@ var Socket = class {
17109
17482
  }
17110
17483
  const { maxAttempts } = this.reconnectConfig;
17111
17484
  if (this.reconnectAttempts >= maxAttempts) {
17485
+ if (this.callKit.connect.isCalling()) {
17486
+ this.callKit.logger.warn("reconnect during call, ignore", {
17487
+ caller: "Socket.attemptReconnect",
17488
+ type: "INCALL",
17489
+ content: {
17490
+ errCode: ErrorCode.SOCKET_RECONNECT_FAILED,
17491
+ isCalling: this.callKit.connect.isCalling(),
17492
+ reconnectAttempts: this.reconnectAttempts
17493
+ }
17494
+ });
17495
+ return;
17496
+ }
17497
+ if (this.isUserSetPingTryCount) {
17498
+ this.callKit.trigger(KitEvent.INCALL_CONNECT_EVENT, {
17499
+ event: "INCALL_PING_TIMEOUT_RECONNECT_FAILED_MAX_ATTEMPTS"
17500
+ });
17501
+ }
17112
17502
  this.callKit.trigger(KitEvent.INCALL_CONNECT_EVENT, {
17113
17503
  event: "INCALL_RECONNECT_ERROR"
17114
17504
  });
17115
17505
  this.setConnectAuthState("isError", true);
17116
17506
  this.callKit.reset();
17117
- this.callKit.logger.error("Maximum reconnection attempts reached", {
17118
- caller: "Socket.attemptReconnect",
17119
- type: "INCALL",
17120
- content: {
17121
- errCode: ErrorCode.SOCKET_RECONNECT_FAILED,
17122
- reconnectAttempts: this.reconnectAttempts
17507
+ this.callKit.logger.warn(
17508
+ "Maximum reconnection attempts reached, trigger reset",
17509
+ {
17510
+ caller: "Socket.attemptReconnect",
17511
+ type: "INCALL",
17512
+ content: {
17513
+ errCode: ErrorCode.SOCKET_RECONNECT_FAILED,
17514
+ reconnectAttempts: this.reconnectAttempts,
17515
+ delayReset: this.callKit.connect.isCalling()
17516
+ }
17123
17517
  }
17124
- });
17518
+ );
17125
17519
  return;
17126
17520
  }
17127
17521
  if (this.reconnectAttempts === 0) {
@@ -17227,6 +17621,7 @@ var CallKit = class {
17227
17621
  content: {
17228
17622
  username,
17229
17623
  password,
17624
+ ua: navigator.userAgent,
17230
17625
  encryptionMethod,
17231
17626
  encryptionPassword
17232
17627
  }
@@ -17246,6 +17641,7 @@ var CallKit = class {
17246
17641
  });
17247
17642
  if (user) {
17248
17643
  this.config.setConfig("userInfo", {
17644
+ ...user,
17249
17645
  wsUrl: `wss://${user.wsUrl}`,
17250
17646
  sessionId: user.sessionId,
17251
17647
  username,
@@ -17260,6 +17656,9 @@ var CallKit = class {
17260
17656
  iceInfo: user.iceInfo,
17261
17657
  iceGatheringTimeout: user.iceGatheringTimeout,
17262
17658
  logGather: user.logGather,
17659
+ keepaliveInterval: user.keepaliveInterval,
17660
+ pingTryCount: user?.pingTryCount,
17661
+ pingTryCountInterval: user?.pingTryCountInterval,
17263
17662
  phoneType: user.phoneType,
17264
17663
  // encryptionType is in extra
17265
17664
  ...extra
@@ -17537,4 +17936,3 @@ var CallKit = class {
17537
17936
  export {
17538
17937
  CallKit
17539
17938
  };
17540
- //# sourceMappingURL=index.mjs.map