2015-01-14 3 views
1

Я хочу создать телефон-вызывающий внутри моего приложения Java. Для этого кукол я использовал библиотеку JAIN-SIP. После первого INVITE системе требуется прокси-аутентификация. Второй пригласят в conscructed с помощью «AuthenticationHelperImpl.class»: https://gitorious.org/0xdroid/external_nist-sip/source/1e0f37693341071f316852c8e05a08deef2b7fc4:java/gov/nist/javax/sip/clientauthutils/AuthenticationHelperImpl.java#L311, включает в себя заголовок Proxy-Authentication и lloks как:Как сделать телефонный звонок SIP

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

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

После этого я получаю в начинающемся коде 100 сообщения ("Ваш звонок очень важен для нас »), за которым следует 408 кодовых сообщений (« Тайм-аут запроса »).

То, что я сделал imporve ситуации:

  1. пытался форматы номера отличаются телефоном: 004930208488480, 04930208488480, 049, 0049, sdfhajfkhsk. Для всех этих чисел I становится такой же комбинацией сообщений.

  2. пытался использовать порт в URI Запроса

  3. пытался удалить maddr из запроса URI.

  4. попытался заполнить тело сообщения с помощью настроек кода.

  5. для установки и удаления rport с помощью заголовка

Если вы теперь, что я делаю не так, пожалуйста, помогите мне. Спасибо заранее.

+0

Это похоже на проблему с NAT. Контролируйте трафик с обеих сторон, чтобы увидеть, где сообщение потеряно. Вы рекламируете свой сетевой адрес везде 192.168.17.107:34567. Попробуйте TCP вместо UDP, чтобы проверить, он должен работать лучше в этом случае и может быть достаточно. В противном случае просмотрите STUN и TURN или проверьте свою удаленную сторону, если она может быть сконфигурирована для компенсации NAT в некотором роде. –

ответ

0

Проблема была частично решена при удалении «maddr = fpbx.de» из URI запроса и из proxy-auth.URI

FPR это используемый метод handleCahllenge с логическими аргументами:

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

Но я до сих пор не знаю, как я могу с acchieve sponaneous номер телефона.

2

Я думаю, может быть, ваш прокси-авторизационный заголовок неверен. Возможно, вы просчитались. Я хотел поделиться своим решением.

authUser - ваш номер телефона. (например: 77735hk6iu) authPass - пароль пользователя. тзд Ваш запрос пригласить (Headers!)

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.

Удачи!

+0

спасибо) До вашего ответа я также понял, что проблема была в этой «maddr» части прокси-заголовка. Но ваш код также очень полезен. – user2957954

0

Сообщение 100 - hop-by-hop, то есть просто означает, что следующий прыжок получил ваш запрос. Другие сообщения обычно будут сквозными (поэтому, если вы получили 180 звонков, это обычно означает, что конечная точка называется отправленной 180). 408 обычно появляется, когда один из хэмов отправил INVITE, но так и не получил ответа (и ваш стек SIP может генерировать это внутренне, когда он не получает предварительный ответ в разумные сроки - обычно около 32 секунд с по умолчанию SIP-таймеры).

Я не знаю вашу настройку сети, но в этом сообщении есть несколько частных IP-адресов (из разновидности 192.168.x.x). Если бы я должен был догадаться, ваш первый прыжок отправляет 100 обратно на IP-порт, из которого он был получен, но следующий ответ следует за заголовками Via (как и должно быть), а прыжок после того, как вы не уважаете rport параметр, поэтому ответ становится потерянным. Кроме того, ваш NAT плохо настроен и слишком быстро закрывает отверстие, созданное для INVITE.

Если у вас есть прокси-сервер на краю вашей сети, что это сообщение выходит, оно либо помещает плохие заголовки Via в сообщение (возможно, с внутренним IP-адресом вместо внешнего IP-адреса), либо отправляет INVITE в неправильное место (заставляя его никогда не получать ответа), и 408 исходит от него.

Смежные вопросы