Я использую JAIN-SIP для регистрации на сервере Asterisk и для инициирования вызова с помощью другого программного телефона SIP. Для Asterisk я запускаю конфигурацию по умолчанию для http://www.raspberry-asterisk.org/ с добавлением некоторых расширений (пользователей SIP).Asterisk/JAIN-SIP Почему мне нужно несколько раз проверять подлинность?
Когда я отправляю сообщение REGISTER в Asterisk, сервер (Asterisk) отправляет запрос проверки подлинности, как ожидалось. Моя проблема заключается в том, что, как только я отвечу на эту проблему, Asterisk снова попросит повторить аутентификацию. После второго ответа на аутентификацию он, наконец, принят. Я не понимаю, почему он работает таким образом, поэтому я предполагаю, что у меня должно быть что-то очень неправильное.
Пример кода:
package sip.test.example;
import gov.nist.javax.sip.SipStackExt;
import gov.nist.javax.sip.clientauthutils.*;
import javax.sip.*;
import javax.sip.address.*;
import javax.sip.header.*;
import javax.sip.message.*;
import java.util.*;
public class WhyDoesThisAuthenticateTwice {
private SipStackExt sipStack;
private HeaderFactory header;
private SipProvider udp;
private final String sipId = "2";
private final String myIp = "192.168.1.152";
private final int myPort = 5060;
private final String myPw = "password22";
private final String realm = "asterisk";
private final String asteriskIp = "192.168.1.171";
private final int asteriskPort = 5060;
private final String tag = "fgdfdf";
public static void main(String[] args) throws Exception {
new WhyDoesThisAuthenticateTwice().register();
}
public void register() throws Exception {
SipFactory sipFactory = SipFactory.getInstance();
sipFactory.setPathName("gov.nist");
Properties properties = new Properties();
properties.setProperty("javax.sip.STACK_NAME", "test-phone");
properties.setProperty("javax.sip.OUTBOUND_PROXY", asteriskIp+":"+asteriskPort+"/udp");
this.sipStack = (SipStackExt) sipFactory.createSipStack(properties);
header = sipFactory.createHeaderFactory();
AddressFactory address = sipFactory.createAddressFactory();
MessageFactory message = sipFactory.createMessageFactory();
ListeningPoint udpPoint = sipStack.createListeningPoint(myIp, myPort, "udp");
MySIPListener listener = new MySIPListener();
udp = sipStack.createSipProvider(udpPoint);
udp.addSipListener(listener);
SipURI myRealmURI = address.createSipURI(sipId, realm);
Address fromAddress = address.createAddress(myRealmURI);
fromAddress.setDisplayName(sipId);
FromHeader fromHeader = header.createFromHeader(fromAddress, tag);
SipURI myURI = address.createSipURI(sipId, myIp);
myURI.setPort(myPort);
Address contactAddress = address.createAddress(myURI);
contactAddress.setDisplayName(sipId);
ContactHeader contactHeader = header.createContactHeader(contactAddress);
MaxForwardsHeader maxForwards = header.createMaxForwardsHeader(5);
List<ViaHeader> viaHeaders = new ArrayList<>();
CallIdHeader callIdHeader = udp.getNewCallId();
long seq = 1;
CSeqHeader cSeqHeader = header.createCSeqHeader(seq++, Request.REGISTER);
ToHeader toHeader = header.createToHeader(fromAddress, null);
URI requestURI = address.createURI("sip:"+asteriskIp+":"+asteriskPort);
Request request = message.createRequest(requestURI, Request.REGISTER, callIdHeader,
cSeqHeader, fromHeader, toHeader, viaHeaders, maxForwards);
request.addHeader(contactHeader);
ExpiresHeader eh = header.createExpiresHeader(300);
request.addHeader(eh);
ClientTransaction transaction = udp.getNewClientTransaction(request);
transaction.sendRequest();
System.out.println("Sent request:");
System.out.println(request);
}
private class MySIPListener implements SipListener {
@Override
public void processRequest(RequestEvent requestEvent) {}
@Override
public void processResponse(ResponseEvent event) {
try {
Response response = event.getResponse();
System.out.println("Response received:");
System.out.println(response);
if (response.getStatusCode() != 401) return;
ClientTransaction tid = event.getClientTransaction();
AccountManagerImpl manager = new AccountManagerImpl();
AuthenticationHelper helper = sipStack.getAuthenticationHelper(manager, header);
ClientTransaction transaction = helper.handleChallenge(response, tid, udp, 5);
transaction.sendRequest();
Request request = transaction.getRequest();
System.out.println("Sent request with authentication info:");
System.out.println(request);
} catch (SipException e) { e.printStackTrace(); }
}
@Override
public void processTimeout(TimeoutEvent timeoutEvent) {}
@Override
public void processIOException(IOExceptionEvent exceptionEvent) {}
@Override
public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {}
@Override
public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {}
}
private class AccountManagerImpl implements AccountManager {
@Override
public UserCredentials getCredentials(ClientTransaction clientTransaction, String s) {
return new UserCredentials() {
@Override
public String getUserName() { return sipId; }
@Override
public String getPassword() { return myPw; }
@Override
public String getSipDomain() { return realm; }
};
}
}
}
Когда я запускаю его, это то, что я получаю:
Sent request:
REGISTER sip:192.168.1.171:5060 SIP/2.0
Call-ID: [email protected]
CSeq: 1 REGISTER
From: "2" <sip:[email protected]>;tag=fgdfdf
To: "2" <sip:[email protected]>
Max-Forwards: 5
Contact: "2" <sip:[email protected]:5060>
Expires: 300
Via: SIP/2.0/UDP 192.168.1.152:5060;branch=z9hG4bK-373634-2421c1e13c920e5a75f69f9a3f80f8d8
Content-Length: 0
Response received:
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 192.168.1.152:5060;branch=z9hG4bK-373634-2421c1e13c920e5a75f69f9a3f80f8d8;received=192.168.1.152
From: "2" <sip:[email protected]>;tag=fgdfdf
To: "2" <sip:[email protected]>;tag=as42a729fa
Call-ID: [email protected]
CSeq: 1 REGISTER
Server: FPBX-2.11.0(11.6.0)
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,REFER,SUBSCRIBE,NOTIFY,INFO,PUBLISH
Supported: replaces,timer
WWW-Authenticate: Digest algorithm=MD5,realm="asterisk",nonce="5bdc425c"
Content-Length: 0
Sent request with authentication info:
REGISTER sip:192.168.1.171:5060;maddr=192.168.1.171 SIP/2.0
Call-ID: [email protected]
CSeq: 2 REGISTER
From: "2" <sip:[email protected]>;tag=fgdfdf
To: "2" <sip:[email protected]>
Max-Forwards: 5
Contact: "2" <sip:[email protected]:5060>
Expires: 300
Via: SIP/2.0/UDP 192.168.1.152:5060;branch=z9hG4bK-373634-18fc265c4d5854f9a970d7545facd464
Authorization: Digest username="2",realm="asterisk",nonce="5bdc425c",uri="sip:192.168.1.171:5060;maddr=192.168.1.171",response="6dc54ff9338920a9b6d7d8755ce719cc",algorithm=MD5
Content-Length: 0
Response received:
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 192.168.1.152:5060;branch=z9hG4bK-373634-18fc265c4d5854f9a970d7545facd464;received=192.168.1.152
From: "2" <sip:[email protected]>;tag=fgdfdf
To: "2" <sip:[email protected]>;tag=as46d30f80
Call-ID: [email protected]
CSeq: 2 REGISTER
Server: FPBX-2.11.0(11.6.0)
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,REFER,SUBSCRIBE,NOTIFY,INFO,PUBLISH
Supported: replaces,timer
WWW-Authenticate: Digest algorithm=MD5,realm="asterisk",nonce="75ac799b"
Content-Length: 0
Sent request with authentication info:
REGISTER sip:192.168.1.171:5060;maddr=192.168.1.171 SIP/2.0
Call-ID: [email protected]
CSeq: 3 REGISTER
From: "2" <sip:[email protected]>;tag=fgdfdf
To: "2" <sip:[email protected]>
Max-Forwards: 5
Contact: "2" <sip:[email protected]:5060>
Expires: 300
Via: SIP/2.0/UDP 192.168.1.152:5060;branch=z9hG4bK-373634-64f022399c1ad437b6fffa21782c9376
Authorization: Digest username="2",realm="asterisk",nonce="75ac799b",uri="sip:192.168.1.171:5060;maddr=192.168.1.171",response="cd18746b954cfca05a65c04a23be4e77",algorithm=MD5
Content-Length: 0
Response received:
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.1.152:5060;branch=z9hG4bK-373634-64f022399c1ad437b6fffa21782c9376;received=192.168.1.152
From: "2" <sip:[email protected]>;tag=fgdfdf
To: "2" <sip:[email protected]>;tag=as46d30f80
Call-ID: [email protected]
CSeq: 3 REGISTER
Server: FPBX-2.11.0(11.6.0)
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,REFER,SUBSCRIBE,NOTIFY,INFO,PUBLISH
Supported: replaces,timer
Expires: 300
Contact: <sip:[email protected]:5060>;expires=300
Date: Mon, 17 Feb 2014 20:27:02 GMT
Content-Length: 0
Как вы можете видеть, я получаю 401 Несанкционированное назад дважды. И время, когда РЕГИСТР отправляется снова с включенным ответом на аутентификацию.
Итак, мой вопрос: почему аутентификация не принимается в первый раз, а на втором? Он выполняется точно таким же кодом.
У меня есть аналогичная проблема с отправкой сообщений INVITE. После успешного РЕГИСТРА, когда я отправляю INVITE, Asterisk требует, чтобы я снова аутентифицировался. Код MySIPListener выше также обрабатывает этот код и выдает требуемый INVITE с ответом на аутентификацию. Тем не менее, все примеры, которые я нахожу в этом, всегда показывают прямое приглашение работать, поскольку, я полагаю, вы должны пройти аутентификацию уже. Возможно, связано с той же проблемой?
Так что я делаю неправильно?
OK, спасибо. Добавление: maddr = 192.168.1.171 к первому URI разрешило эту проблему. Кажется, что класс AuthenticationHelper из JAIN-SIP всегда добавляет его туда, поэтому не может использовать его, не помещая там параметр maddr. Теперь просто нужно выяснить, почему мой INVITE получает то же самое, но это еще одна проблема. –