npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tw-sip

v1.1.1

Published

SDK 现在支持重复登录检查,防止在已登录状态下重复登录导致的资源泄漏和状态混乱。

Readme

TW-SIP SDK

重复登录防护

SDK 现在支持重复登录检查,防止在已登录状态下重复登录导致的资源泄漏和状态混乱。

重连策略优化

SDK 现在采用双层重连机制:

1. WebSocket 层重连

  • 触发条件onDisconnect 事件 + WebSocket 未连接状态
  • 处理场景:网络断开、服务器重启等导致的 WebSocket 连接断开
  • 判断条件this.userAgent && !this.userAgent.isConnected()

2. 注册层重连

  • 触发条件:注册状态变为 UnregisteredTerminated
  • 处理场景:注册会话过期、认证失败等导致的注册断开
  • 判断条件state === RegistererState.Unregistered || state === RegistererState.Terminated

竞态条件修复

修复了快速登出再登录时的竞态条件问题:

// 🔧 问题场景:
// 1. 用户调用 loginOut()
// 2. 立即调用 login() 重新登录成功  
// 3. 几秒后旧的 unregister() 超时,误触发重连
// 4. WebSocket 正常关闭(code: 1000)也会误触发重连
// 5. 旧注册器的状态回调仍然在运行,影响新登录

// ✅ 修复方案:
1. loginOut() 立即清空所有状态,防止异步回调影响
2. 重连逻辑增加精确判断,避免误触发
3. 账号一致性检查,防止旧注册器影响新注册器
4. 新增主动登出标志,防止主动登出时的正常断开触发重连
5. 新增登录会话ID,防止旧登录会话的回调影响新登录

重连逻辑说明

// ❌ 修复前:注册成功时错误地触发重连
if (this.registererState === RegistererState.Registered) {
  sipReConnect(...) // 错误!注册成功为什么要重连?
}

// ✅ 修复后:只在注册失败或断开时重连,且增加精确判断
if (state === RegistererState.Unregistered || state === RegistererState.Terminated) {
  const shouldReconnect = 
    this?.loginInfo?.ip && 
    this?.loginInfo?.authorizationUsername &&
    this?.loginInfo?.authorizationUsername === account.authorizationUsername && // 账号一致性检查
    this.registerer && 
    !this.isLoggedIn(); // 确实未登录
    
  if (shouldReconnect) {
    sipReConnect(...) // 精确重连
  }
}

使用示例

const twSip = new TwSip();

// 检查登录状态
console.log('当前登录状态:', twSip.isLoggedIn());
console.log('详细状态信息:', twSip.getLoginStatus());

// 登录
const loginResult = await twSip.login({
  ip: '192.168.1.100',
  server: 'wss://192.168.1.100:7443',
  aor: 'sip:[email protected]',
  authorizationUsername: '1004',
  authorizationPassword: 'password123'
});

if (loginResult.code === 200) {
  console.log('登录成功');
} else if (loginResult.code === 1002) {
  console.log('已处于登录状态,请先退出登录');
  // 可以选择先退出再登录
  twSip.loginOut();
  // 然后重新登录
}

// 重复登录会被阻止
const duplicateLoginResult = await twSip.login(loginInfo);
console.log(duplicateLoginResult.msg); // "当前已处于登录状态,请先退出登录再重新登录"

// ✅ 快速登出再登录现在是安全的
twSip.loginOut();
// 可以立即重新登录,不会有竞态条件问题
const reLoginResult = await twSip.login(loginInfo);

返回码说明

  • 200: 登录成功
  • 1000: WebSocket 连接失败
  • 1001: 坐席注册失败
  • 1002: 重复登录(新增)

API

isLoggedIn(): boolean

检查当前是否已登录

getLoginStatus(): object

获取详细的登录状态信息,包括:

  • isLoggedIn: 是否已登录
  • registererState: 注册器状态
  • hasUserAgent: 是否有用户代理
  • hasRegisterer: 是否有注册器
  • hasLoginInfo: 是否有登录信息
  • loginInfo: 登录信息(仅在已登录时返回)