/** * Get a dialog identifier. Generates a string that can be used as a dialog identifier. * * @param isServer is set to true if this is the UAS and set to false if this is the UAC */ public String getDialogId(boolean isServer) { CallID cid = (CallID) this.getCallId(); StringBuffer retval = new StringBuffer(cid.getCallId()); From from = (From) this.getFrom(); To to = (To) this.getTo(); if (!isServer) { // retval.append(COLON).append(from.getUserAtHostPort()); if (from.getTag() != null) { retval.append(COLON); retval.append(from.getTag()); } // retval.append(COLON).append(to.getUserAtHostPort()); if (to.getTag() != null) { retval.append(COLON); retval.append(to.getTag()); } } else { // retval.append(COLON).append(to.getUserAtHostPort()); if (to.getTag() != null) { retval.append(COLON); retval.append(to.getTag()); } // retval.append(COLON).append(from.getUserAtHostPort()); if (from.getTag() != null) { retval.append(COLON); retval.append(from.getTag()); } } return retval.toString().toLowerCase(); }
/** * Creates an ACK for non-2xx responses according to RFC3261 17.1.1.3 * * @return A SIPRequest with an ACK method. * @throws SipException * @throws NullPointerException * @throws ParseException * @author jvb */ public final SIPRequest createErrorAck(To responseToHeader) throws SipException, ParseException { /* * The ACK request constructed by the client transaction MUST contain values for the * Call-ID, From, and Request-URI that are equal to the values of those header fields in * the request passed to the transport by the client transaction (call this the "original * request"). The To header field in the ACK MUST equal the To header field in the * response being acknowledged, and therefore will usually differ from the To header field * in the original request by the addition of the tag parameter. The ACK MUST contain a * single Via header field, and this MUST be equal to the top Via header field of the * original request. The CSeq header field in the ACK MUST contain the same value for the * sequence number as was present in the original request, but the method parameter MUST * be equal to "ACK". */ SIPRequest newRequest = new SIPRequest(); newRequest.setRequestLine((RequestLine) this.requestLine.clone()); newRequest.setMethod(Request.ACK); newRequest.setHeader((Header) this.callIdHeader.clone()); newRequest.setHeader((Header) this.maxForwardsHeader.clone()); // ISSUE // 130 // fix newRequest.setHeader((Header) this.fromHeader.clone()); newRequest.setHeader((Header) responseToHeader.clone()); newRequest.addFirst((Header) this.getTopmostVia().clone()); newRequest.setHeader((Header) cSeqHeader.clone()); newRequest.getCSeq().setMethod(Request.ACK); /* * If the INVITE request whose response is being acknowledged had Route header fields, * those header fields MUST appear in the ACK. This is to ensure that the ACK can be * routed properly through any downstream stateless proxies. */ if (this.getRouteHeaders() != null) { newRequest.setHeader((SIPHeaderList) this.getRouteHeaders().clone()); } if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) { newRequest.setHeader(MessageFactoryImpl.getDefaultUserAgentHeader()); } return newRequest; }
/** * Create a new default SIPRequest from the original request. Warning: the newly created * SIPRequest, shares the headers of this request but we generate any new headers that we need to * modify so the original request is umodified. However, if you modify the shared headers after * this request is created, then the newly created request will also be modified. If you want to * modify the original request without affecting the returned Request make sure you clone it * before calling this method. * * <p>Only required headers are copied. * * <ul> * <li>Contact headers are not included in the newly created request. Setting the appropriate * sequence number is the responsibility of the caller. * <li>RouteList is not copied for ACK and CANCEL * <li>Note that we DO NOT copy the body of the argument into the returned header. We do not * copy the content type header from the original request either. These have to be added * seperately and the content length has to be correctly set if necessary the content length * is set to 0 in the returned header. * <li>Contact List is not copied from the original request. * <li>RecordRoute List is not included from original request. * <li>Via header is not included from the original request. * </ul> * * @param requestLine is the new request line. * @param switchHeaders is a boolean flag that causes to and from headers to switch (set this to * true if you are the server of the transaction and are generating a BYE request). If the * headers are switched, we generate new From and To headers otherwise we just use the * incoming headers. * @return a new Default SIP Request which has the requestLine specified. */ public SIPRequest createSIPRequest(RequestLine requestLine, boolean switchHeaders) { SIPRequest newRequest = new SIPRequest(); newRequest.requestLine = requestLine; Iterator headerIterator = this.getHeaders(); while (headerIterator.hasNext()) { SIPHeader nextHeader = (SIPHeader) headerIterator.next(); // For BYE and cancel set the CSeq header to the // appropriate method. if (nextHeader instanceof CSeq) { CSeq newCseq = (CSeq) nextHeader.clone(); nextHeader = newCseq; try { newCseq.setMethod(requestLine.getMethod()); } catch (ParseException e) { } } else if (nextHeader instanceof ViaList) { Via via = (Via) (((ViaList) nextHeader).getFirst().clone()); via.removeParameter("branch"); nextHeader = via; // Cancel and ACK preserve the branch ID. } else if (nextHeader instanceof To) { To to = (To) nextHeader; if (switchHeaders) { nextHeader = new From(to); ((From) nextHeader).removeTag(); } else { nextHeader = (SIPHeader) to.clone(); ((To) nextHeader).removeTag(); } } else if (nextHeader instanceof From) { From from = (From) nextHeader; if (switchHeaders) { nextHeader = new To(from); ((To) nextHeader).removeTag(); } else { nextHeader = (SIPHeader) from.clone(); ((From) nextHeader).removeTag(); } } else if (nextHeader instanceof ContentLength) { ContentLength cl = (ContentLength) nextHeader.clone(); try { cl.setContentLength(0); } catch (InvalidArgumentException e) { } nextHeader = cl; } else if (!(nextHeader instanceof CallID) && !(nextHeader instanceof MaxForwards)) { // Route is kept by dialog. // RR is added by the caller. // Contact is added by the Caller // Any extension headers must be added // by the caller. continue; } try { newRequest.attachHeader(nextHeader, false); } catch (SIPDuplicateHeaderException e) { e.printStackTrace(); } } if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) { newRequest.setHeader(MessageFactoryImpl.getDefaultUserAgentHeader()); } return newRequest; }
/** Called by the sax parser when the start of an element is encountered. */ public void startElement(String nameSpaceURI, String local, String name, Attributes attrs) throws SAXException { try { Debug.println("processing " + name); if (name.compareTo(TagNames.CALLFLOW) == 0) { callFlow = new CallFlow(); callFlow.instantiateOn = attrs.getValue(Attr.instantiateOn); callFlow.description = attrs.getValue(Attr.description); } else if (name.compareTo(TagNames.AGENT) == 0) { Agent agent = new Agent(); agent.agentId = attrs.getValue(Attr.agentId); agent.userName = attrs.getValue(Attr.userName); agent.requestURI = attrs.getValue(Attr.requestURI); agent.host = attrs.getValue(Attr.host); agent.contactPort = attrs.getValue(Attr.contactPort); agent.contactHost = attrs.getValue(Attr.contactHost); addAgent(agent); } else if (name.compareTo(TagNames.EXPECT) == 0) { // Make sure there are no unexpected attributes. for (int i = 0; i < attrs.getLength(); i++) { String attrname = attrs.getLocalName(i); if (attrname.equals(Attr.enablingEvent) || attrname.equals(Attr.triggerMessage) || attrname.equals(Attr.generatedEvent) || attrname.equals(Attr.nodeId) || attrname.equals(Attr.onTrigger) || attrname.equals(Attr.onCompletion)) continue; else throw new SAXException( "Unkown attribute in expect: nodeId = " + attrs.getValue(Attr.nodeId) + " attribute name = " + attrname); } String enablingEvent = attrs.getValue(Attr.enablingEvent); String triggerMessage = attrs.getValue(Attr.triggerMessage); String generatedEvent = attrs.getValue(Attr.generatedEvent); String nodeId = attrs.getValue(Attr.nodeId); currentExpectNode = new Expect(callFlow, enablingEvent, generatedEvent, triggerMessage); String onTrigger = attrs.getValue(Attr.onTrigger); String onCompletion = attrs.getValue(Attr.onCompletion); currentExpectNode.onTrigger = onTrigger; currentExpectNode.onCompletion = onCompletion; currentExpectNode.nodeId = nodeId; } else if (name.compareTo(TagNames.SIP_REQUEST) == 0) { if (this.messageTemplateContext) { // This is a SIPRequest template node. for (int i = 0; i < attrs.getLength(); i++) { String attrname = attrs.getLocalName(i); if (!attrs.getLocalName(i).equals(Attr.templateId)) throw new SAXException( "Unkown attribute in SIP_REQUEST node " + " attribute name = " + attrname); } messageTemplate = new SIPRequest(); id = attrs.getValue(Attr.templateId); jythonCode = null; } } else if (name.compareTo(TagNames.SIP_RESPONSE) == 0) { if (this.messageTemplateContext) { messageTemplate = new SIPResponse(); jythonCode = null; for (int i = 0; i < attrs.getLength(); i++) { String attrname = attrs.getLocalName(i); if (!attrs.getLocalName(i).equals(Attr.templateId)) throw new SAXException( "Unkown attribute in SIP_REQUEST node " + " attribute name = " + attrname); } id = attrs.getValue(Attr.templateId); } } else if (name.compareTo(TagNames.STATUS_LINE) == 0) { String scode = attrs.getValue(Attr.statusCode); if (messageTemplateContext) { StatusLine statusLine = new StatusLine(); try { int statusCode = Integer.parseInt(scode); statusLine.setStatusCode(statusCode); } catch (NumberFormatException ex) { throw new SAXException(ex.getMessage()); } SIPResponse response = (SIPResponse) this.messageTemplate; response.setStatusLine(statusLine); } else { int statusCode = Integer.parseInt(scode); generatedMessage.addStatusLine(statusCode); } } else if (name.compareTo(TagNames.REQUEST_LINE) == 0) { String method = attrs.getValue(Attr.method); Debug.println("tagname = " + TagNames.REQUEST_LINE); Debug.println("messageTemplateContext = " + messageTemplateContext); if (messageTemplateContext) { for (int i = 0; i < attrs.getLength(); i++) { String attrname = attrs.getLocalName(i); if (attrs.getLocalName(i).equals(Attr.requestURI) || attrs.getLocalName(i).equals(Attr.method)) continue; else throw new SAXException( "Unkown attribute in REQUEST_LINE node " + " attribute name = " + attrname); } requestLine = new RequestLine(); requestLine.setMethod(method); String requestURI = attrs.getValue(Attr.requestURI); StringMsgParser smp = new StringMsgParser(); if (requestURI != null) { try { URI uri = smp.parseSIPUrl(requestURI); requestLine.setUri(uri); } catch (SIPParseException e) { throw new SAXException("Bad URL " + requestURI); } } SIPRequest request = (SIPRequest) messageTemplate; request.setRequestLine(requestLine); } else { for (int i = 0; i < attrs.getLength(); i++) { String attrname = attrs.getLocalName(i); if (attrs.getLocalName(i).equals(Attr.method) || attrs.getLocalName(i).equals(Attr.templateId) || attrs.getLocalName(i).equals(Attr.agentId)) continue; else throw new SAXException( "Unkown attribute in REQUEST_LINE node " + " attribute name = " + attrname); } String requestURI = attrs.getValue(Attr.requestURI); if (requestURI == null) { String agentId = attrs.getValue(Attr.agentId); if (agentId != null) { Agent agent = getAgent(agentId); if (agent == null) throw new SAXException("Missing requestURI or agent attribute"); requestURI = agent.requestURI; } } generatedMessage.addRequestLine(method, requestURI); } } else if (name.compareTo(TagNames.FROM) == 0) { for (int i = 0; i < attrs.getLength(); i++) { String attrname = attrs.getLocalName(i); if (attrs.getLocalName(i).equals(Attr.displayName) || attrs.getLocalName(i).equals(Attr.userName) || attrs.getLocalName(i).equals(Attr.host) || attrs.getLocalName(i).equals(Attr.agentId)) continue; else throw new SAXException( "Unkown attribute in FROM node " + " attribute name = " + attrname); } String displayName = attrs.getValue(Attr.displayName); String userName = attrs.getValue(Attr.userName); String hostName = attrs.getValue(Attr.host); String agentId = attrs.getValue(Attr.agentId); if (agentId != null) { Agent agent = getAgent(agentId); if (agent == null) throw new SAXException("agent not found " + agentId); if (displayName == null) displayName = agent.displayName; if (userName == null) userName = agent.userName; if (hostName == null) hostName = agent.host; } if (this.messageTemplateContext) { From from = new From(); Address address = new Address(); address.setDisplayName(displayName); URI uri = new URI(); Host host = new Host(); host.setHostname(hostName); uri.setHost(host); uri.setUser(userName); address.setAddrSpec(uri); from.setAddress(address); try { messageTemplate.attachHeader(from, false); } catch (SIPDuplicateHeaderException ex) { throw new SAXException(ex.getMessage()); } } else { generatedMessage.addFromHeader(displayName, userName, hostName); } } else if (name.compareTo(TagNames.TO) == 0) { for (int i = 0; i < attrs.getLength(); i++) { String attrname = attrs.getLocalName(i); if (attrs.getLocalName(i).equals(Attr.templateId) || attrs.getLocalName(i).equals(Attr.host) || attrs.getLocalName(i).equals(Attr.agentId) || attrs.getLocalName(i).equals(Attr.userName)) continue; else throw new SAXException( "Unkown attribute in FROM node " + " attribute name = " + attrname); } String displayName = attrs.getValue(Attr.displayName); String userName = attrs.getValue(Attr.userName); String hostName = attrs.getValue(Attr.host); String agentId = attrs.getValue(Attr.agentId); if (agentId != null) { Agent agent = getAgent(agentId); if (agent == null) throw new SAXException("agent not found " + agentId); if (displayName == null) displayName = agent.displayName; if (userName == null) userName = agent.userName; if (hostName == null) hostName = agent.host; } if (this.messageTemplateContext) { To to = new To(); Address address = new Address(); address.setDisplayName(displayName); URI uri = new URI(); Host host = new Host(); host.setHostname(hostName); uri.setHost(host); uri.setUser(userName); address.setAddrSpec(uri); to.setAddress(address); try { messageTemplate.attachHeader(to, false); } catch (SIPDuplicateHeaderException ex) { throw new SAXException(ex.getMessage()); } } else { generatedMessage.addToHeader(displayName, userName, hostName); } } else if (name.compareTo(TagNames.CALLID) == 0) { String lid = attrs.getValue(Attr.localId); String host = attrs.getValue(Attr.host); if (this.messageTemplateContext) { CallID cid = new CallID(); CallIdentifier cidf = new CallIdentifier(lid, host); cid.setCallIdentifier(cidf); } else { generatedMessage.addCallIdHeader(); } } else if (name.compareTo(TagNames.CONTACT) == 0) { for (int i = 0; i < attrs.getLength(); i++) { String attrname = attrs.getLocalName(i); if (attrs.getLocalName(i).equals(Attr.displayName) || attrs.getLocalName(i).equals(Attr.userName) || attrs.getLocalName(i).equals(Attr.action) || attrs.getLocalName(i).equals(Attr.contactHost) || attrs.getLocalName(i).equals(Attr.contactPort) || attrs.getLocalName(i).equals(Attr.agentId) || attrs.getLocalName(i).equals(Attr.expires)) continue; else throw new SAXException( "Unkown attribute in CONTACT node " + " attribute name = " + attrname); } String displayName = attrs.getValue(Attr.displayName); String userName = attrs.getValue(Attr.userName); String hostName = attrs.getValue(Attr.contactHost); String portString = attrs.getValue(Attr.contactPort); String expiryTimeString = attrs.getValue(Attr.expires); String action = attrs.getValue(Attr.action); String agentId = attrs.getValue(Attr.agentId); if (action == null) action = "proxy"; if (agentId != null) { Agent agent = getAgent(agentId); if (displayName == null) displayName = agent.displayName; if (userName == null) userName = agent.userName; if (hostName == null) hostName = agent.contactHost; if (portString == null) portString = agent.contactPort; } if (this.messageTemplateContext) { // Generating a message template for the expires header. ContactList clist = new ContactList(); Contact contact = new Contact(); clist.add(contact); URI uri = new URI(); Host host = new Host(); host.setHostname(hostName); uri.setHost(host); uri.setUser(userName); if (portString != null) { int port = new Integer(portString).intValue(); uri.setPort(port); } Address address = new Address(); address.setAddrSpec(uri); contact.setAddress(address); if (expiryTimeString != null) { long expiryTimeSec = new Long(expiryTimeString).longValue(); contact.setExpires(expiryTimeSec); } messageTemplate.attachHeader(clist, false); } else { int port = 5060; if (portString != null) port = new Integer(portString).intValue(); long expiryTimeSec = 3600; if (expiryTimeString != null) { expiryTimeSec = new Long(expiryTimeString).longValue(); } if (userName == null) throw new Exception("Missing attribute userName"); if (action == null) action = Attr.proxy; String uri; if (hostName == null) { uri = SIPKeywords.SIP + Separators.COLON + userName + Separators.AT + EventEngine.theStack.getHostAddress() + Separators.COLON + EventEngine.theStack.getDefaultPort() + Separators.SEMICOLON + SIPKeywords.TRANSPORT + Separators.EQUALS + EventEngine.theStack.getDefaultTransport(); } else uri = SIPKeywords.SIP + Separators.COLON + userName + Separators.AT + hostName + ":" + port; generatedMessage.addContactHeader(displayName, uri, expiryTimeSec, action); } } else if (name.compareTo(TagNames.GENERATE) == 0) { generateContext = true; if (currentExpectNode == null) { throw new SAXException("Bad element nesting."); } String id = attrs.getValue(Attr.messageId); String retransmit = attrs.getValue(Attr.retransmit); String delayString = attrs.getValue(Attr.delay); int delay = 0; if (delayString != null) { try { delay = Integer.parseInt(delayString); } catch (NumberFormatException ex) { throw new SAXException("Bad integer value " + delayString); } } generatedMessage = new GeneratedMessage(id, callFlow, currentExpectNode, retransmit); generatedMessage.delay = delay; currentExpectNode.addGeneratedMessage(generatedMessage); } else if (name.compareTo(TagNames.MESSAGE_TEMPLATES) == 0) { messageTemplateContext = true; } else if (name.compareTo(TagNames.JYTHON_CODE) == 0) { this.jythonCode = null; } else if (name.compareTo(TagNames.STATE_MACHINE) == 0) { } else if (name.compareTo(TagNames.AGENTS) == 0) { } else { throw new SAXException("Unkown tag " + name); } } catch (Exception ex) { ex.printStackTrace(); ex.fillInStackTrace(); throw new SAXException(ex.getMessage()); } }