【问题标题】:How do I do a SIP telephone call如何进行 SIP 电话呼叫
【发布时间】:2015-01-14 15:24:05
【问题描述】:

我想在我的 java 应用程序中构造一个电话呼叫者。为此,我使用了 JAIN-SIP 库。在第一次 INVITE 之后,系统需要 Proxy-Authentication。第二个邀请是在 "AuthenticationHelperImpl.class":https://gitorious.org/0xdroid/external_nist-sip/source/1e0f37693341071f316852c8e05a08deef2b7fc4:java/gov/nist/javax/sip/clientauthutils/AuthenticationHelperImpl.java#L311 的帮助下构建的,包括 Proxy-Authentication 标头和类似以下内容:

INVITE sip:+11111111111@fpbx.de;maddr=fpbx.de SIP/2.0
Call-ID: 1c609509a43b721ab11c396c1e6ea9e7@192.168.17.107
CSeq: 2 INVITE
From: "77735hk6iu" <sip:77735hk6iu@fpbx.de>
To: "+111111111111111" <sip:+11111111111@fpbx.de>
Via: SIP/2.0/UDP 192.168.17.107:34567;rport;branch=z9hG4bK-383337-5bc4fd6b7a616843fce9eaa243bcb10e
Max-Forwards: 70
Contact: <sip:77735hk6iu@192.168.17.107:5060>
Content-Type: application/sdp
Proxy-Authorization: Digest       username="77735hk6iu",realm="fpbx.de",nonce="VLaIxVS2h5muPS30F2zLdXHjup6ELyen",uri="sip:+111111111111@fpbx.de:5060;maddr=fpbx.de",response="47ea578c6b01c99fd3ed2b41c60983df"
Content-Length: 61

v=0
o=- 130565705777141827 1 IN IP4 192.168.17.107
s=call

之后我在开始收到代码 100 消息(“您的电话对我们非常重要”),然后是 408 代码消息(“请求超时”)。

我做了什么来改善这种情况:

  1. 尝试了不同的电话号码格式:004930208488480, 04930208488480, 049, 0049, sdfhajfkhsk。对于所有这些数字,我 成为消息上的相同组合。

  2. 尝试在请求 uri 中使用端口

  3. 试图从请求 uri 中删除 maddr。

  4. 尝试使用 codek 设置填充邮件正文。

  5. 通过标头设置和删除 rport

如果你现在我做错了什么,请帮助我。 提前谢谢你。

【问题讨论】:

  • 看起来是 NAT 问题。监视双方的流量以查看消息丢失的位置。您在 192.168.17.107:34567 处宣传您的专用网络地址。尝试使用 TCP 而不是 UDP 来验证,在这种情况下它应该会更好地工作并且可能就足够了。否则,请查看 STUN 和 TURN 或检查您的远程方是否可以配置为以某种方式补偿 NAT。

标签: java sip telephony jain-sip


【解决方案1】:

我想,也许您的 Proxy-Authorization 标头是错误的。可能你算错了。我想分享我的决心。

authUser 是您的电话号码。 (例如:77735hk6iu) authPass 是您的用户密码。 msg 是您的邀请请求。(标题!)

AccountManagerImpl accountManagerImp = new AccountManagerImpl(authUser, AuthPass);
        AuthenticationHelperImpl authenticationHelperImpl = new AuthenticationHelperImpl(accountManagerImp);

        try {
           this.authentication = authenticationHelperImpl.handleChallenge(msg, (SIPClientTransaction)trans);

AuthenticationHelperImple.java 类:

   public AuthorizationHeader handleChallenge(Response challenge, ClientTransaction challengedTransaction) throws SipException {


  SIPRequest challengedRequest = ((SIPRequest) challengedTransaction.getRequest());

  ListIterator authHeaders = null;

  if (challenge.getStatusCode() == Response.UNAUTHORIZED) {
     authHeaders = challenge.getHeaders(WWWAuthenticateHeader.NAME);
  }
  else {
     if (challenge.getStatusCode() == Response.PROXY_AUTHENTICATION_REQUIRED) {
        authHeaders = challenge.getHeaders(ProxyAuthenticateHeader.NAME);
     }
     else {
        throw new IllegalArgumentException("Unexpected status code ");
     }
  }

  if (authHeaders == null) {
     throw new IllegalArgumentException("Could not find WWWAuthenticate or ProxyAuthenticate headers");
  }

  WWWAuthenticateHeader authHeader = null;
  while (authHeaders.hasNext()) {
     authHeader = (WWWAuthenticateHeader) authHeaders.next();
     String realm = authHeader.getRealm();

     this.uri = challengedRequest.getRequestURI();

     this.requestMethod = challengedRequest.getMethod();
     this.requestBody = (challengedRequest.getContent() == null) ? "" : new String(challengedRequest.getRawContent());

     if (this.accountManager instanceof SecureAccountManager) {
        UserCredentialHash credHash = ((SecureAccountManager) this.accountManager).getCredentialHash(challengedTransaction,
                                                                                                     realm);
        if (credHash == null) {
           logger.logDebug("Could not find creds");
           throw new SipException("Cannot find user creds for the given user name and realm");
        }

        this.authorizationHeader = this.getAuthorization(requestMethod, uri.toString(), requestBody, authHeader, credHash);
     }
     else {
        UserCredentials userCreds = ((AccountManager) this.accountManager).getCredentials(challengedTransaction, realm);
        if (userCreds == null) {
           throw new SipException("Cannot find user creds for the given user name and realm");
        }
        // sipDomain = userCreds.getSipDomain();
        // we haven't yet authenticated this realm since we were
        // started.

       this.authorizationHeader = this.getAuthorization(requestMethod, uri.toString(), requestBody, authHeader, userCreds);
     }
  }

  return this.authorizationHeader;

}

getAuthorization 函数:

 public AuthorizationHeader getAuthorization(String method,
                                           String uri,
                                           String requestBody,
                                           WWWAuthenticateHeader authHeader,
                                           UserCredentials userCredentials) throws SecurityException {
  String response = null;
  String qopList = authHeader.getQop();
  String qop = (qopList != null) ? "auth" : null;
  String nc_value = "00000001";
  String cnonce = "xyz";

  try {
     response = MessageDigestAlgorithm.calculateResponse(authHeader.getAlgorithm(),
                                                        userCredentials.getUserName(), authHeader.getRealm(),userCredentials.getPassword(), authHeader.getNonce(), nc_value, // JvB added
                                                 cnonce, // JvB added
                                                 method, uri, requestBody, qop,logger);
  }
  catch (NullPointerException exc) {
     throw new SecurityException("The received authenticate header was malformatted: " + exc.getMessage());
  }

  AuthorizationHeader authorization = null;
  try {
      if (authHeader instanceof ProxyAuthenticateHeader) {
         if (this.headerFactory != null) {
            authorization = headerFactory.createProxyAuthorizationHeader(authHeader.getScheme());
         }
         else {
            authorization = new ProxyAuthorization();
            authorization.setScheme(authHeader.getScheme()); 
         }
      } 
      else {
         if (this.headerFactory != null) {
            authorization = headerFactory.createAuthorizationHeader(authHeader.getScheme());
         }
         else {
            authorization = new Authorization();
            authorization.setScheme(authHeader.getScheme());
         }
      }

      authorization.setUsername(userCredentials.getUserName());
      authorization.setRealm(authHeader.getRealm());
      authorization.setNonce(authHeader.getNonce());
      authorization.setParameter("uri", uri);
      authorization.setResponse(response);
      if (authHeader.getAlgorithm() != null) {
          authorization.setAlgorithm(authHeader.getAlgorithm());
      }

      if (authHeader.getOpaque() != null) {
          authorization.setOpaque(authHeader.getOpaque());
      }

      // jvb added
      if (qop != null) {
          authorization.setQop(qop);
          authorization.setCNonce(cnonce);
          authorization.setNonceCount(Integer.parseInt(nc_value));
      }

      authorization.setResponse(response);

  } catch (ParseException ex) {
      throw new RuntimeException("Failed to create an authorization header!");
  }

  return authorization;

}

最后,您的 this.authentication 变量是 ProxyAuthorizationHeader。您必须将 this.authentication 放入您的 INVITE 消息中。并且您会将 SipMessage 从事务或对话发送到 JAIN-SIP 堆栈。

祝你好运!

【讨论】:

  • 谢谢你)在你回答之前,我也明白问题出在代理头的这个“maddr”部分。但是你的代码也很有帮助。
【解决方案2】:

从请求 URI 和代理身份验证中删除“maddr=fpbx.de”后,问题部分解决了。乌里

fpr 这是一个使用过的带有布尔参数的 handleCahllenge 方法:

inviteTid = authenticationHelper.handleChallenge(response, tid, sipProvider, 15, **true**);

但我仍然不知道如何获得自发电话号码。

【讨论】:

    【解决方案3】:

    100消息是逐跳的,也就是说它只是意味着下一跳得到了你的请求。其他消息通常是端到端的(因此,如果您收到 180 Ringing,这通常意味着被调用的端点发送了 180)。当其中一个跃点发送 INVITE 但从未得到响应时,通常会显示 408(并且您的 SIP 堆栈可能会在内部生成它,因为它在合理的时间范围内没有得到临时响应 - 通常约为 32 秒,默认值SIP 定时器)。

    我不知道您的网络设置,但该消息中有几个专用 IP(属于 192.168.x.x 种类)。如果我不得不猜测,您的第一个跃点是将 100 发送回它接收它的 IP/端口,但下一个响应是遵循 Via 标头(应该如此),并且在您不尊重 rport 之后的跃点参数,所以响应会丢失。或者,您的 NAT 配置不当,并且过快地关闭了它为 INVITE 创建的漏洞。

    如果您的网络边缘有代理发送此消息,则它要么在消息上放置了错误的 Via 标头(可能使用内部 IP 而不是外部 IP),要么正在向其发送 INVITE错误的地方(导致它永远不会得到响应),并且 408 来自它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多