/** * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.ifsoft.sip; import java.io.IOException; import java.text.*; import java.util.*; import javax.sip.*; import javax.sip.address.*; import javax.sip.header.*; import javax.sip.message.*; import org.slf4j.*; import org.slf4j.Logger; //import org.jitsi.videobridge.openfire.PluginImpl; public class RegisterProcessing implements SipListener { private static final Logger Log = LoggerFactory.getLogger(RegisterProcessing.class); private Request registerRequest = null; private boolean isRegistered = false; private Timer reRegisterTimer = new Timer(); private String registrar; private String address; private VideoBridgeSipListener.SipServerCallback sipServerCallback; private String sipCallId; int registrarPort = 5060; int expires = 120; private HeaderFactory headerFactory = SipService.getHeaderFactory(); private AddressFactory addressFactory = SipService.getAddressFactory(); private MessageFactory messageFactory = SipService.getMessageFactory(); private SipProvider sipProvider = SipService.getSipProvider(); public ProxyCredentials proxyCredentials; public RegisterProcessing(String address, String registrar, ProxyCredentials proxyCredentials) { Log.info("Start registering...." + registrar); this.registrar = registrar; this.proxyCredentials = proxyCredentials; this.address = address; sipServerCallback = VideoBridgeSipListener.getSipServerCallback(); try { register(); } catch (IOException e) { Log.info(e.getMessage()); } } public void processRequest(RequestEvent requestReceivedEvent) { Log.info("Request ignored: " + requestReceivedEvent.getRequest()); } public void processResponse(ResponseEvent responseReceivedEvent) { Log.info("Registering response...." + sipCallId); Response response = (Response)responseReceivedEvent.getResponse(); int statusCode = response.getStatusCode(); String method = ((CSeqHeader) response.getHeader(CSeqHeader.NAME)).getMethod(); Log.debug("Got response " + response); if (statusCode == Response.OK) { isRegistered = true; Log.info("RegisterProcessing successfully registered with " + registrar + " for " + proxyCredentials.getUserName() + " user " + proxyCredentials.getXmppUserName()); //PluginImpl.sipRegisterStatus = "Registered ok with " + proxyCredentials.getHost(); sipServerCallback.removeSipListener(sipCallId); } else if (statusCode == Response.UNAUTHORIZED || statusCode == Response.PROXY_AUTHENTICATION_REQUIRED) { if (method.equals(Request.REGISTER)) { CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME); if (cseq.getSequenceNumber() < 2) { ClientTransaction regTrans = SipService.handleChallenge(response, responseReceivedEvent.getClientTransaction(), proxyCredentials); if (regTrans != null) { try { regTrans.sendRequest(); } catch (Exception e) { Log.info("Registration failed, cannot send transaction " + e); //PluginImpl.sipRegisterStatus = "Registration error " + e.toString(); } } else { Log.info("Registration failed, cannot create transaction"); //PluginImpl.sipRegisterStatus = "Registration cannot create transaction"; } } else { Log.info("Registration failed " + responseReceivedEvent); //PluginImpl.sipRegisterStatus = "Registration failed"; } } } else { Log.info("Unrecognized response: " + response); } } public void processTimeout(TimeoutEvent timeoutEvent) { Log.info("Timeout trying to register with " + registrar); sipServerCallback.removeSipListener(sipCallId); } public void processDialogTerminated(DialogTerminatedEvent dte) { Log.debug("processDialogTerminated called"); sipServerCallback.removeSipListener(sipCallId); } public void processTransactionTerminated(TransactionTerminatedEvent tte) { Log.debug("processTransactionTerminated called"); sipServerCallback.removeSipListener(sipCallId); } public void processIOException(IOExceptionEvent ioee) { Log.debug("processTransactionTerminated called"); sipServerCallback.removeSipListener(sipCallId); } private void register() throws IOException { Log.info("Registering with " + registrar); FromHeader fromHeader = getFromHeader(); Address fromAddress = fromHeader.getAddress(); //Request URI SipURI requestURI = null; try { requestURI = addressFactory.createSipURI(null, registrar); } catch (ParseException e) { throw new IOException("Bad registrar address:" + registrar + " " + e.getMessage()); } //requestURI.setPort(registrarPort); try { requestURI.setTransportParam( sipProvider.getListeningPoint().getTransport()); } catch (ParseException e) { throw new IOException(sipProvider.getListeningPoint().getTransport() + " is not a valid transport! " + e.getMessage()); } CallIdHeader callIdHeader = sipProvider.getNewCallId(); CSeqHeader cSeqHeader = null; try { cSeqHeader = headerFactory.createCSeqHeader(1, Request.REGISTER); } catch (ParseException e) { //Should never happen throw new IOException("Corrupt Sip Stack " + e.getMessage()); } catch (InvalidArgumentException e) { //Should never happen throw new IOException("The application is corrupt " ); } ToHeader toHeader = null; try { String proxyWorkAround = System.getProperty("com.sun.mc.softphone.REGISTRAR_WORKAROUND"); if (proxyWorkAround != null && proxyWorkAround.toUpperCase().equals("TRUE")) { SipURI toURI = (SipURI)(requestURI.clone()); toURI.setUser(System.getProperty("user.name")); toHeader = headerFactory.createToHeader( addressFactory.createAddress(toURI), null); } else { toHeader = headerFactory.createToHeader(fromAddress, null); } } catch (ParseException e) { throw new IOException("Could not create a To header for address:" + fromHeader.getAddress() + " " + e.getMessage()); } ArrayList viaHeaders = getLocalViaHeaders(); MaxForwardsHeader maxForwardsHeader = getMaxForwardsHeader(); Request request = null; try { request = messageFactory.createRequest(requestURI, Request.REGISTER, callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, maxForwardsHeader); } catch (ParseException e) { throw new IOException("Could not create the register request! " + e.getMessage()); } ExpiresHeader expHeader = null; for (int retry = 0; retry < 2; retry++) { try { expHeader = headerFactory.createExpiresHeader( expires); } catch (InvalidArgumentException e) { if (retry == 0) { continue; } throw new IOException( "Invalid registrations expiration parameter - " + expires + " " + e.getMessage()); } } request.addHeader(expHeader); ContactHeader contactHeader = getRegistrationContactHeader(); request.addHeader(contactHeader); try { SipURI routeURI = (SipURI) addressFactory.createURI("sip:" + proxyCredentials.getProxy() + ";lr"); RouteHeader routeHeader = headerFactory.createRouteHeader(addressFactory.createAddress(routeURI)); request.addHeader(routeHeader); } catch (Exception e) { Log.error("Creating registration route error ", e); } ClientTransaction regTrans = null; try { regTrans = sipProvider.getNewClientTransaction(request); } catch (TransactionUnavailableException e) { throw new IOException("Could not create a register transaction!\n" + "Check that the Registrar address is correct! " + e.getMessage()); } try { sipCallId = callIdHeader.getCallId(); sipServerCallback.addSipListener(sipCallId, this); registerRequest = request; regTrans.sendRequest(); Log.debug("Sent register request " + registerRequest); if (expires > 0) { scheduleReRegistration(); } } catch (Exception e) { throw new IOException("Could not send out the register request! "+ e.getMessage()); } this.registerRequest = request; } public void unregister() throws IOException { if (!isRegistered) { return; } cancelPendingRegistrations(); isRegistered = false; if (this.registerRequest == null) { Log.info("Couldn't find the initial register request"); throw new IOException("Couldn't find the initial register request"); } Request unregisterRequest = (Request) registerRequest.clone(); try { unregisterRequest.getExpires().setExpires(0); CSeqHeader cSeqHeader = (CSeqHeader)unregisterRequest.getHeader(CSeqHeader.NAME); //[issue 1] - increment registration cseq number //reported by - Roberto Tealdi <roby.tea@tin.it> cSeqHeader.setSequenceNumber(cSeqHeader.getSequenceNumber()+1); } catch (InvalidArgumentException e) { Log.info("Unable to set Expires Header " + e.getMessage()); return; } ClientTransaction unregisterTransaction = null; try { unregisterTransaction = sipProvider.getNewClientTransaction( unregisterRequest); } catch (TransactionUnavailableException e) { throw new IOException("Unable to create a unregister transaction " + e.getMessage()); } try { unregisterTransaction.sendRequest(); } catch (SipException e) { Log.info("Faied to send unregister request " + e.getMessage()); return; } } public boolean isRegistered() { return isRegistered; } private FromHeader fromHeader; private FromHeader getFromHeader() throws IOException { if (fromHeader != null) { return fromHeader; } try { SipURI fromURI = (SipURI) addressFactory.createURI("sip:" + proxyCredentials.getUserName() + "@" + registrar); fromURI.setTransportParam(sipProvider.getListeningPoint().getTransport()); fromURI.setPort(sipProvider.getListeningPoint().getPort()); Address fromAddress = addressFactory.createAddress(fromURI); fromAddress.setDisplayName(proxyCredentials.getUserDisplay()); fromHeader = headerFactory.createFromHeader(fromAddress, Integer.toString(hashCode())); } catch (ParseException e) { throw new IOException( "A ParseException occurred while creating From Header! " + e.getMessage()); } return fromHeader; } private ArrayList viaHeaders; private ArrayList getLocalViaHeaders() throws IOException { /* * We can't keep a cached copy because the callers * of this method change the viaHeaders. In particular * a branch may be added which causes INVITES to fail. */ if (viaHeaders != null) { return viaHeaders; } ListeningPoint lp = sipProvider.getListeningPoint(); viaHeaders = new ArrayList(); try { String addr = lp.getIPAddress(); ViaHeader viaHeader = headerFactory.createViaHeader( addr, lp.getPort(), lp.getTransport(), null); viaHeader.setRPort(); viaHeaders.add(viaHeader); return viaHeaders; } catch (ParseException e) { throw new IOException ( "A ParseException occurred while creating Via Headers! " + e.getMessage()); } catch (InvalidArgumentException e) { throw new IOException( "Unable to create a via header for port " + lp.getPort() + " " + e.getMessage()); } } private static final int MAX_FORWARDS = 70; private MaxForwardsHeader maxForwardsHeader; private MaxForwardsHeader getMaxForwardsHeader() throws IOException { if (maxForwardsHeader != null) { return maxForwardsHeader; } try { maxForwardsHeader = headerFactory.createMaxForwardsHeader(MAX_FORWARDS); return maxForwardsHeader; } catch (InvalidArgumentException e) { throw new IOException( "A problem occurred while creating MaxForwardsHeader " + e.getMessage()); } } private ContactHeader contactHeader; private ContactHeader getRegistrationContactHeader() throws IOException { if (contactHeader != null) { return contactHeader; } try { SipURI contactURI = (SipURI) addressFactory.createURI("sip:" + proxyCredentials.getUserName() + "@" + proxyCredentials.getHost()); contactURI.setTransportParam( sipProvider.getListeningPoint().getTransport()); contactURI.setPort(sipProvider.getListeningPoint().getPort()); Address contactAddress = addressFactory.createAddress(contactURI); contactAddress.setDisplayName(proxyCredentials.getUserDisplay()); contactHeader = headerFactory.createContactHeader(contactAddress); return contactHeader; } catch (ParseException e) { throw new IOException( "A ParseException occurred while creating From Header! " + " " + e.getMessage()); } } class ReRegisterTask extends TimerTask { public ReRegisterTask() { } public void run() { try { if (isRegistered()) { register(); } } catch (IOException e) { Log.info("Failed to reRegister " + e.getMessage()); } } } private void cancelPendingRegistrations() { reRegisterTimer.cancel(); reRegisterTimer = null; reRegisterTimer = new Timer(); } private void scheduleReRegistration() { ReRegisterTask reRegisterTask = new ReRegisterTask(); reRegisterTimer.schedule(reRegisterTask, expires * 1000); } }