From 4ff93fb55b0efea8b4acf6b0767772a32df9c8bc Mon Sep 17 00:00:00 2001 From: Emil Ivov Date: Mon, 28 Sep 2009 09:59:30 +0000 Subject: [PATCH] Refactoring OperationSetBasicTelephonySipImpl in preparation of the pending media/SDP modifications --- .../impl/protocol/sip/CallSipImpl.java | 4 + .../OperationSetBasicTelephonySipImpl.java | 87 ++-- .../sip/ProtocolProviderServiceSipImpl.java | 4 +- .../impl/protocol/sip/SipMessageFactory.java | 372 ++++++++++++++++-- .../sip/util/JainSipTelephonyHelper.java | 275 ------------- 5 files changed, 375 insertions(+), 367 deletions(-) delete mode 100644 src/net/java/sip/communicator/impl/protocol/sip/util/JainSipTelephonyHelper.java diff --git a/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java index c19cccc35..02fc2dd00 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java @@ -132,6 +132,7 @@ public int getCallPeerCount() */ public void peerImageChanged(CallPeerChangeEvent evt) { + //does not concern us } /** @@ -142,6 +143,7 @@ public void peerImageChanged(CallPeerChangeEvent evt) */ public void peerAddressChanged(CallPeerChangeEvent evt) { + //does not concern us } /** @@ -153,6 +155,7 @@ public void peerAddressChanged(CallPeerChangeEvent evt) public void peerTransportAddressChanged( CallPeerChangeEvent evt) { + //does not concern us } /** @@ -163,6 +166,7 @@ public void peerTransportAddressChanged( */ public void peerDisplayNameChanged(CallPeerChangeEvent evt) { + //does not concern us } /** diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java index 3769559fe..501dcdcd6 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java @@ -48,6 +48,12 @@ public class OperationSetBasicTelephonySipImpl */ private final ProtocolProviderServiceSipImpl protocolProvider; + /** + * A reference to the SipMessageFactory instance that we should + * use when creating requests. + */ + private final SipMessageFactory messageFactory; + /** * Contains references for all currently active (non ended) calls. */ @@ -76,6 +82,7 @@ public OperationSetBasicTelephonySipImpl( ProtocolProviderServiceSipImpl protocolProvider) { this.protocolProvider = protocolProvider; + this.messageFactory = protocolProvider.getMessageFactory(); protocolProvider.registerMethodProcessor(Request.INVITE, this); protocolProvider.registerMethodProcessor(Request.CANCEL, this); @@ -166,31 +173,13 @@ public Call createCall(Contact callee) throws OperationFailedException private synchronized CallSipImpl createOutgoingCall(Address calleeAddress, javax.sip.message.Message cause) throws OperationFailedException { - if(!protocolProvider.isRegistered()) - { - throw new OperationFailedException( - "The protocol provider should be registered " - +"before placing an outgoing call.", - OperationFailedException.PROVIDER_NOT_REGISTERED); - } + assertRegistered(); // create the invite request - Request invite = JainSipTelephonyHelper - .createInviteRequest(calleeAddress, protocolProvider); - + Request invite = messageFactory.createInviteRequest(calleeAddress); // pre-authenticate the request if possible. - JainSipTelephonyHelper.preAuthenticateRequest(); - - /* - * Whatever the cause of the outgoing call is, reflect the appropriate - * information from it into the INVITE request (and do it elsewhere - * because this method is already long enough and difficult to grasp). - */ - if (cause != null) - { - reflectCauseOnEffect(cause, invite); - } + messageFactory.preAuthenticateRequest(invite); // Transaction ClientTransaction inviteTransaction = null; @@ -282,43 +271,6 @@ private synchronized CallSipImpl createOutgoingCall(Address calleeAddress, return (CallSipImpl) callPeer.getCall(); } - /** - * Copies and possibly modifies information from a given SIP - * Message into another SIP Message (the first of - * which is being thought of as the cause for the existence of the second - * and the second is considered the effect of the first for the sake of - * clarity in the most common of use cases). - *

- * The Referred-By header and its optional token are common examples of such - * information which is to be copied without modification by the referee - * from the REFER Request into the resulting Request - * to the refer target. - *

- * - * @param cause the SIP Message from which the information is - * to be copied - * @param effect the SIP Message into which the information is - * to be copied - */ - private void reflectCauseOnEffect(javax.sip.message.Message cause, - javax.sip.message.Message effect) - { - - /* - * Referred-By (which comes from a referrer) should be copied to the - * refer target without tampering. - * - * TODO Apart from Referred-By, its token should also be copied if - * present. - */ - Header referredBy = cause.getHeader(ReferredByHeader.NAME); - - if (referredBy != null) - { - effect.setHeader(referredBy); - } - } - /** * Returns an iterator over all currently active calls. * @@ -3144,5 +3096,24 @@ private Address parseAddressString(String addressString) } return address; } + + /** + * Verifies that our protocol provider is properly registered and throws + * an OperationFailedException if that's not the case. + * + * @throws OperationFailedException if the protocol provider that created us + * is not registered. + */ + private void assertRegistered() + throws OperationFailedException + { + if(!protocolProvider.isRegistered()) + { + throw new OperationFailedException( + "The protocol provider should be registered " + +"before placing an outgoing call.", + OperationFailedException.PROVIDER_NOT_REGISTERED); + } + } } diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java index edc6b4cdc..fa2b3c2f8 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java @@ -75,7 +75,7 @@ public class ProtocolProviderServiceSipImpl /** * The Message Factory used to create SIP messages. */ - private MessageFactory messageFactory; + private SipMessageFactory messageFactory; /** * The class in charge of event dispatching and managing common JAIN-SIP @@ -1156,7 +1156,7 @@ public HeaderFactory getHeaderFactory() * * @return the Message Factory used to create SIP messages. */ - public MessageFactory getMessageFactory() + public SipMessageFactory getMessageFactory() { if (messageFactory == null) { diff --git a/src/net/java/sip/communicator/impl/protocol/sip/SipMessageFactory.java b/src/net/java/sip/communicator/impl/protocol/sip/SipMessageFactory.java index c6918c23b..396ce1ab4 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/SipMessageFactory.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/SipMessageFactory.java @@ -6,13 +6,17 @@ */ package net.java.sip.communicator.impl.protocol.sip; +import gov.nist.javax.sip.header.extensions.*; + import java.text.*; import java.util.*; +import javax.sip.*; import javax.sip.address.*; import javax.sip.header.*; import javax.sip.message.*; +import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.util.*; /** @@ -37,17 +41,17 @@ public class SipMessageFactory * The service this SipMessageFactory belongs to; * used to mark messages. */ - private final ProtocolProviderServiceSipImpl service_; + private final ProtocolProviderServiceSipImpl protocolProvider; /** * The wrapped factory. SipMessageFactory does nothing by itself * and will just forward method calls to factory_ (besides marking * messages). */ - private final MessageFactory factory_; + private final MessageFactory wrappedFactory; /** - * The contructor for this class. + * The constructor for this class. * * @param service the service this MessageFactory belongs to. * @param wrappedFactory the MessageFactory which will really @@ -61,8 +65,8 @@ public SipMessageFactory(ProtocolProviderServiceSipImpl service, if (wrappedFactory == null) throw new NullPointerException("wrappedFactory is null"); - this.service_ = service; - this.factory_ = wrappedFactory; + this.protocolProvider = service; + this.wrappedFactory = wrappedFactory; } /** @@ -77,10 +81,10 @@ public Request createRequest(URI requestURI, String method, CallIdHeader Object content) throws ParseException { - Request request = this.factory_.createRequest(requestURI, method, + Request request = this.wrappedFactory.createRequest(requestURI, method, callId, cSeq, from, to, via, maxForwards, contentType, content); SipApplicationData.setApplicationData(request, - SipApplicationData.KEY_SERVICE, this.service_); + SipApplicationData.KEY_SERVICE, this.protocolProvider); return request; } @@ -96,10 +100,10 @@ public Request createRequest(URI requestURI, String method, CallIdHeader byte[] content) throws ParseException { - Request request = this.factory_.createRequest(requestURI, method, + Request request = this.wrappedFactory.createRequest(requestURI, method, callId, cSeq, from, to, via, maxForwards, contentType, content); SipApplicationData.setApplicationData(request, - SipApplicationData.KEY_SERVICE, this.service_); + SipApplicationData.KEY_SERVICE, this.protocolProvider); return request; } @@ -114,10 +118,10 @@ public Request createRequest(URI requestURI, String method, CallIdHeader MaxForwardsHeader maxForwards) throws ParseException { - Request request = this.factory_.createRequest(requestURI, method, + Request request = this.wrappedFactory.createRequest(requestURI, method, callId, cSeq, from, to, via, maxForwards); SipApplicationData.setApplicationData(request, - SipApplicationData.KEY_SERVICE, this.service_); + SipApplicationData.KEY_SERVICE, this.protocolProvider); return request; } @@ -130,9 +134,9 @@ public Request createRequest(URI requestURI, String method, CallIdHeader public Request createRequest(String requestParam) throws ParseException { - Request request = this.factory_.createRequest(requestParam); + Request request = this.wrappedFactory.createRequest(requestParam); SipApplicationData.setApplicationData(request, - SipApplicationData.KEY_SERVICE, this.service_); + SipApplicationData.KEY_SERVICE, this.protocolProvider); return request; } @@ -148,10 +152,10 @@ public Response createResponse(int statusCode, CallIdHeader callId, Object content) throws ParseException { - Response response = this.factory_.createResponse(statusCode, callId, - cSeq, from, to, via, maxForwards, contentType, content); + Response response = this.wrappedFactory.createResponse(statusCode, + callId, cSeq, from, to, via, maxForwards, contentType, content); SipApplicationData.setApplicationData(response, - SipApplicationData.KEY_SERVICE, this.service_); + SipApplicationData.KEY_SERVICE, this.protocolProvider); return response; } @@ -167,10 +171,10 @@ public Response createResponse(int statusCode, CallIdHeader callId, byte[] content) throws ParseException { - Response response = this.factory_.createResponse(statusCode, callId, - cSeq, from, to, via, maxForwards, contentType, content); + Response response = this.wrappedFactory.createResponse(statusCode, + callId, cSeq, from, to, via, maxForwards, contentType, content); SipApplicationData.setApplicationData(response, - SipApplicationData.KEY_SERVICE, this.service_); + SipApplicationData.KEY_SERVICE, this.protocolProvider); return response; } @@ -185,10 +189,10 @@ public Response createResponse(int statusCode, CallIdHeader callId, MaxForwardsHeader maxForwards) throws ParseException { - Response response = this.factory_.createResponse(statusCode, callId, - cSeq, from, to, via, maxForwards); + Response response = this.wrappedFactory.createResponse(statusCode, + callId, cSeq, from, to, via, maxForwards); SipApplicationData.setApplicationData(response, - SipApplicationData.KEY_SERVICE, this.service_); + SipApplicationData.KEY_SERVICE, this.protocolProvider); return response; } @@ -202,10 +206,10 @@ public Response createResponse(int statusCode, Request request, ContentTypeHeader contentType, Object content) throws ParseException { - Response response = this.factory_.createResponse(statusCode, request, - contentType, content); + Response response = this.wrappedFactory.createResponse(statusCode, + request, contentType, content); SipApplicationData.setApplicationData(response, - SipApplicationData.KEY_SERVICE, this.service_); + SipApplicationData.KEY_SERVICE, this.protocolProvider); return response; } @@ -219,10 +223,10 @@ public Response createResponse(int statusCode, Request request, ContentTypeHeader contentType, byte[] content) throws ParseException { - Response response = this.factory_.createResponse(statusCode, request, - contentType, content); + Response response = this.wrappedFactory.createResponse(statusCode, + request, contentType, content); SipApplicationData.setApplicationData(response, - SipApplicationData.KEY_SERVICE, this.service_); + SipApplicationData.KEY_SERVICE, this.protocolProvider); return response; } @@ -235,9 +239,10 @@ public Response createResponse(int statusCode, Request request, public Response createResponse(int statusCode, Request request) throws ParseException { - Response response = this.factory_.createResponse(statusCode, request); + Response response + = this.wrappedFactory.createResponse(statusCode, request); SipApplicationData.setApplicationData(response, - SipApplicationData.KEY_SERVICE, this.service_); + SipApplicationData.KEY_SERVICE, this.protocolProvider); return response; } @@ -250,11 +255,314 @@ public Response createResponse(int statusCode, Request request) public Response createResponse(String responseParam) throws ParseException { - Response response = this.factory_.createResponse(responseParam); + Response response = this.wrappedFactory.createResponse(responseParam); SipApplicationData.setApplicationData(response, - SipApplicationData.KEY_SERVICE, this.service_); + SipApplicationData.KEY_SERVICE, this.protocolProvider); return response; } //---------------- higher level methods ---------------------------------- + /** + * Creates an invite request destined for callee. + * + * @param toAddress the sip address of the callee that the request is meant + * for. + * + * @return a newly created sip Request destined for callee + * . + * @throws OperationFailedException with the corresponding code if creating + * the request fails. + * @throws IllegalArgumentException if toAddress does not appear + * to be a valid destination. + */ + public Request createInviteRequest( Address toAddress) + throws OperationFailedException, IllegalArgumentException + { + // Call ID + CallIdHeader callIdHeader = protocolProvider.getDefaultJainSipProvider() + .getNewCallId(); + + // CSeq + HeaderFactory headerFactory = protocolProvider.getHeaderFactory(); + CSeqHeader cSeqHeader = null; + try + { + cSeqHeader = headerFactory.createCSeqHeader(1l, Request.INVITE); + } + catch (InvalidArgumentException ex) + { + // Shouldn't happen + throwOperationFailedException("An unexpected erro occurred while" + + "constructing the CSeqHeadder", + OperationFailedException.INTERNAL_ERROR, ex); + } + catch (ParseException exc) + { + // shouldn't happen + throwOperationFailedException("An unexpected erro occurred while" + + "constructing the CSeqHeadder", + OperationFailedException.INTERNAL_ERROR, exc); + } + + // ReplacesHeader + Header replacesHeader = stripReplacesHeader(toAddress); + + // FromHeader + String localTag = ProtocolProviderServiceSipImpl.generateLocalTag(); + FromHeader fromHeader = null; + ToHeader toHeader = null; + try + { + // FromHeader + fromHeader = + headerFactory.createFromHeader( + protocolProvider.getOurSipAddress(toAddress), localTag); + + // ToHeader + toHeader = headerFactory.createToHeader(toAddress, null); + } + catch (ParseException ex) + { + // these two should never happen. + throwOperationFailedException("An unexpected erro occurred while" + + "constructing the ToHeader", + OperationFailedException.INTERNAL_ERROR, ex); + } + + // ViaHeaders + ArrayList viaHeaders = + protocolProvider.getLocalViaHeaders(toAddress); + + // MaxForwards + MaxForwardsHeader maxForwards = protocolProvider.getMaxForwardsHeader(); + + // Contact + ContactHeader contactHeader = null; + try + { + contactHeader + = protocolProvider.getContactHeader(toHeader.getAddress()); + } + catch (IllegalArgumentException exc) + { + // encapsulate the illegal argument exception into an OpFailedExc + // so that the UI would notice it. + throw new OperationFailedException( + exc.getMessage(), + OperationFailedException.ILLEGAL_ARGUMENT, + exc); + } + + Request invite = null; + try + { + invite = + protocolProvider.getMessageFactory().createRequest( + toHeader.getAddress().getURI(), Request.INVITE, + callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, + maxForwards); + + } + catch (ParseException ex) + { + // shouldn't happen + throwOperationFailedException("Failed to create invite Request!", + OperationFailedException.INTERNAL_ERROR, ex); + } + + // User Agent + UserAgentHeader userAgentHeader + = protocolProvider.getSipCommUserAgentHeader(); + if (userAgentHeader != null) + invite.addHeader(userAgentHeader); + + // add the contact header. + invite.addHeader(contactHeader); + + // Add the ReplacesHeader if any. + if (replacesHeader != null) + { + invite.setHeader(replacesHeader); + } + + return invite; + } + + /** + * Creates an invite request destined for callee. + * + * @param toAddress the sip address of the callee that the request is meant + * for. + * @param cause the SIP Message from which the information is + * to be copied + * + * @return a newly created sip Request destined for + * callee. + * + * @throws OperationFailedException with the corresponding code if creating + * the request fails. + * @throws IllegalArgumentException if toAddress does not appear + * to be a valid destination. + */ + public Request createInviteRequest( Address toAddress, + javax.sip.message.Message cause) + throws OperationFailedException, IllegalArgumentException + { + Request invite = createInviteRequest(toAddress); + + /* + * Whatever the cause of the outgoing call is, reflect the appropriate + * information from it into the INVITE request (and do it elsewhere + * because this method is already long enough and difficult to grasp). + */ + if (cause != null) + { + reflectCauseOnEffect(cause, invite); + } + + return invite; + } + + /** + * Copies and possibly modifies information from a given SIP + * Message into another SIP Message (the first of + * which is being thought of as the cause for the existence of the second + * and the second is considered the effect of the first for the sake of + * clarity in the most common of use cases). + *

+ * The Referred-By header and its optional token are common examples of such + * information which is to be copied without modification by the referee + * from the REFER Request into the resulting Request + * to the refer target. + *

+ * + * @param cause the SIP Message from which the information is + * to be copied + * @param effect the SIP Message into which the information is + * to be copied + */ + private void reflectCauseOnEffect(javax.sip.message.Message cause, + javax.sip.message.Message effect) + { + + /* + * Referred-By (which comes from a referrer) should be copied to the + * refer target without tampering. + * + * TODO Apart from Referred-By, its token should also be copied if + * present. + */ + Header referredBy = cause.getHeader(ReferredByHeader.NAME); + + if (referredBy != null) + { + effect.setHeader(referredBy); + } + } + + /** + * Returns the ReplacesHeader contained, if any, in the + * URI of a specific Address after removing it + * from there. + * + * @param address the Address which is to have its + * URI examined and modified + * + * @return a Header which represents the Replaces header + * contained in the URI of the specified + * address; null if no such header is + * present + */ + private Header stripReplacesHeader( Address address ) + throws OperationFailedException + { + javax.sip.address.URI uri = address.getURI(); + Header replacesHeader = null; + + if (uri.isSipURI()) + { + SipURI sipURI = (SipURI) uri; + String replacesHeaderValue = sipURI.getHeader(ReplacesHeader.NAME); + + if (replacesHeaderValue != null) + { + for (Iterator headerNameIter = sipURI.getHeaderNames(); + headerNameIter.hasNext();) + { + if (ReplacesHeader.NAME.equals(headerNameIter.next())) + { + headerNameIter.remove(); + break; + } + } + + try + { + replacesHeader = + protocolProvider.getHeaderFactory().createHeader( + ReplacesHeader.NAME, replacesHeaderValue); + } + catch (ParseException ex) + { + throw new OperationFailedException( + "Failed to create ReplacesHeader from " + + replacesHeaderValue, + OperationFailedException.INTERNAL_ERROR, ex); + } + } + } + return replacesHeader; + } + + /** + * Logs a specific message and associated Throwable cause as an + * error using the current Logger and then throws a new + * OperationFailedException with the message, a specific error code + * and the cause. + * + * @param message the message to be logged and then wrapped in a new + * OperationFailedException + * @param errorCode the error code to be assigned to the new + * OperationFailedException + * @param cause the Throwable that has caused the necessity to log + * an error and have a new OperationFailedException + * thrown + * @throws OperationFailedException + */ + private void throwOperationFailedException(String message, + int errorCode, + Throwable cause) + throws OperationFailedException + { + logger.error(message, cause); + throw new OperationFailedException(message, errorCode, cause); + } + + /** + * Verifies wither we have already authenticated requests with the same + * Call-ID as request and attaches the corresponding + * credentials in an effort to avoid receiving an authentication challenge + * from the server and having to resend the request. This method has no + * effect if the Call-ID has not been seen by our security manager. + * + * @param request the request that we'd like to try pre-authenticating. + * @param service_ the provider where the request originated. + */ + public void preAuthenticateRequest( Request request ) + { + //check whether there's a cached authorization header for this + // call id and if so - attach it to the request. + // add authorization header + CallIdHeader callIdHeader + = (CallIdHeader) request.getHeader(CallIdHeader.NAME); + String callid = callIdHeader.getCallId(); + + AuthorizationHeader authorization = + protocolProvider.getSipSecurityManager() + .getCachedAuthorizationHeader(callid); + + if (authorization != null) + request.addHeader(authorization); + + } } diff --git a/src/net/java/sip/communicator/impl/protocol/sip/util/JainSipTelephonyHelper.java b/src/net/java/sip/communicator/impl/protocol/sip/util/JainSipTelephonyHelper.java deleted file mode 100644 index 5862125d5..000000000 --- a/src/net/java/sip/communicator/impl/protocol/sip/util/JainSipTelephonyHelper.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. - * - * Distributable under LGPL license. - * See terms of license at gnu.org. - */ -package net.java.sip.communicator.impl.protocol.sip.util; - -import gov.nist.javax.sip.header.extensions.*; - -import java.text.*; -import java.util.*; - -import javax.sip.*; -import javax.sip.address.*; -import javax.sip.header.*; -import javax.sip.message.*; - -import net.java.sip.communicator.impl.protocol.sip.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -/** - * The class contains a number of utility methods dealing with construction of - * messages related to telephony. - * - * @author Emil Ivov - */ -public class JainSipTelephonyHelper -{ - private static final Logger logger - = Logger.getLogger(JainSipTelephonyHelper.class); - - /** - * Creates an invite request destined for callee. - * - * @param toAddress the sip address of the callee that the request is meant - * for. - * @param protocolProvider a reference to the protocol provider that is - * creating the request. - * - * @return a newly created sip Request destined for callee - * . - * @throws OperationFailedException with the corresponding code if creating - * the request fails. - * @throws IllegalArgumentException if toAddress does not appear - * to be a valid destination. - */ - public static Request createInviteRequest( - Address toAddress, - ProtocolProviderServiceSipImpl protocolProvider) - throws OperationFailedException, IllegalArgumentException - { - // Call ID - CallIdHeader callIdHeader = - protocolProvider.getDefaultJainSipProvider().getNewCallId(); - - // CSeq - HeaderFactory headerFactory = protocolProvider.getHeaderFactory(); - CSeqHeader cSeqHeader = null; - try - { - cSeqHeader = headerFactory.createCSeqHeader(1l, Request.INVITE); - } - catch (InvalidArgumentException ex) - { - // Shouldn't happen - throwOperationFailedException("An unexpected erro occurred while" - + "constructing the CSeqHeadder", - OperationFailedException.INTERNAL_ERROR, ex); - } - catch (ParseException exc) - { - // shouldn't happen - throwOperationFailedException("An unexpected erro occurred while" - + "constructing the CSeqHeadder", - OperationFailedException.INTERNAL_ERROR, exc); - } - - // ReplacesHeader - Header replacesHeader - = stripReplacesHeader(toAddress, protocolProvider); - - // FromHeader - String localTag = ProtocolProviderServiceSipImpl.generateLocalTag(); - FromHeader fromHeader = null; - ToHeader toHeader = null; - try - { - // FromHeader - fromHeader = - headerFactory.createFromHeader( - protocolProvider.getOurSipAddress(toAddress), localTag); - - // ToHeader - toHeader = headerFactory.createToHeader(toAddress, null); - } - catch (ParseException ex) - { - // these two should never happen. - throwOperationFailedException("An unexpected erro occurred while" - + "constructing the ToHeader", - OperationFailedException.INTERNAL_ERROR, ex); - } - - // ViaHeaders - ArrayList viaHeaders = - protocolProvider.getLocalViaHeaders(toAddress); - - // MaxForwards - MaxForwardsHeader maxForwards = protocolProvider.getMaxForwardsHeader(); - - // Contact - ContactHeader contactHeader = null; - try - { - contactHeader - = protocolProvider.getContactHeader(toHeader.getAddress()); - } - catch (IllegalArgumentException exc) - { - // encapsulate the illegal argument exception into an OpFailedExc - // so that the UI would notice it. - throw new OperationFailedException( - exc.getMessage(), - OperationFailedException.ILLEGAL_ARGUMENT, - exc); - } - - Request invite = null; - try - { - invite = - protocolProvider.getMessageFactory().createRequest( - toHeader.getAddress().getURI(), Request.INVITE, - callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, - maxForwards); - - } - catch (ParseException ex) - { - // shouldn't happen - throwOperationFailedException("Failed to create invite Request!", - OperationFailedException.INTERNAL_ERROR, ex); - } - - // User Agent - UserAgentHeader userAgentHeader = - protocolProvider.getSipCommUserAgentHeader(); - if (userAgentHeader != null) - invite.addHeader(userAgentHeader); - - // add the contact header. - invite.addHeader(contactHeader); - - // Add the ReplacesHeader if any. - if (replacesHeader != null) - { - invite.setHeader(replacesHeader); - } - - return invite; - } - - /** - * Returns the ReplacesHeader contained, if any, in the - * URI of a specific Address after removing it - * from there. - * - * @param address the Address which is to have its - * URI examined and modified - * @param protocolProvider a reference to the protocol provider that is - * creating the request. - * - * @return a Header which represents the Replaces header - * contained in the URI of the specified - * address; null if no such header is - * present - */ - private static Header stripReplacesHeader( - Address address, - ProtocolProviderServiceSipImpl protocolProvider) - throws OperationFailedException - { - javax.sip.address.URI uri = address.getURI(); - Header replacesHeader = null; - - if (uri.isSipURI()) - { - SipURI sipURI = (SipURI) uri; - String replacesHeaderValue = sipURI.getHeader(ReplacesHeader.NAME); - - if (replacesHeaderValue != null) - { - for (Iterator headerNameIter = sipURI.getHeaderNames(); - headerNameIter.hasNext();) - { - if (ReplacesHeader.NAME.equals(headerNameIter.next())) - { - headerNameIter.remove(); - break; - } - } - - try - { - replacesHeader = - protocolProvider.getHeaderFactory().createHeader( - ReplacesHeader.NAME, replacesHeaderValue); - } - catch (ParseException ex) - { - throw new OperationFailedException( - "Failed to create ReplacesHeader from " - + replacesHeaderValue, - OperationFailedException.INTERNAL_ERROR, ex); - } - } - } - return replacesHeader; - } - - /** - * Logs a specific message and associated Throwable cause as an - * error using the current Logger and then throws a new - * OperationFailedException with the message, a specific error code - * and the cause. - * - * @param message the message to be logged and then wrapped in a new - * OperationFailedException - * @param errorCode the error code to be assigned to the new - * OperationFailedException - * @param cause the Throwable that has caused the necessity to log - * an error and have a new OperationFailedException - * thrown - * @throws OperationFailedException - */ - private static void throwOperationFailedException(String message, - int errorCode, - Throwable cause) throws OperationFailedException - { - logger.error(message, cause); - throw new OperationFailedException(message, errorCode, cause); - } - - /** - * Verifies wither we have already authenticated requests with the same - * Call-ID as request and attaches the corresponding - * credentials in an effort to avoid receiving an authentication challenge - * from the server and having to resend the request. This method has no - * effect if the Call-ID has not been seen by our security manager. - * - * @param request the request that we'd like to try pre-authenticating. - * @param protocolProvider the provider where the request originated. - */ - public static void preAuthenticateRequest( - Request request, - ProtocolProviderServiceSipImpl protocolProvider) - { - //check whether there's a cached authorization header for this - // call id and if so - attach it to the request. - // add authorization header - CallIdHeader callIdHeader - = (CallIdHeader) request.getHeader(CallIdHeader.NAME); - String callid = callIdHeader.getCallId(); - - AuthorizationHeader authorization = - protocolProvider.getSipSecurityManager() - .getCachedAuthorizationHeader(callid); - - if (authorization != null) - request.addHeader(authorization); - - } -}