/** * Creates a default SIPResponse message for this request. Note You must add the necessary tags to * outgoing responses if need be. For efficiency, this method does not clone the incoming request. * If you want to modify the outgoing response, be sure to clone the incoming request as the * headers are shared and any modification to the headers of the outgoing response will result in * a modification of the incoming request. Tag fields are just copied from the incoming request. * Contact headers are removed from the incoming request. Added by Jeff Keyser. Route headers are * not added to the response. * * @param statusCode Status code for the response. * @param reasonPhrase Reason phrase for this response. * @return A SIPResponse with the status and reason supplied, and a copy of all the original * headers from this request except the ones that are not supposed to be part of the response * . */ public SIPResponse createResponse(int statusCode, String reasonPhrase) { SIPResponse newResponse; Iterator headerIterator; SIPHeader nextHeader; newResponse = new SIPResponse(); try { newResponse.setStatusCode(statusCode); } catch (ParseException ex) { throw new IllegalArgumentException("Bad code " + statusCode); } if (reasonPhrase != null) newResponse.setReasonPhrase(reasonPhrase); else newResponse.setReasonPhrase(SIPResponse.getReasonPhrase(statusCode)); headerIterator = getHeaders(); while (headerIterator.hasNext()) { nextHeader = (SIPHeader) headerIterator.next(); if (nextHeader instanceof From || nextHeader instanceof To || nextHeader instanceof ViaList || nextHeader instanceof CallID || (nextHeader instanceof RecordRouteList && mustCopyRR(statusCode)) || nextHeader instanceof CSeq // We just copy TimeStamp for all headers (not just 100). || nextHeader instanceof TimeStamp) { try { newResponse.attachHeader((SIPHeader) nextHeader.clone(), false); } catch (SIPDuplicateHeaderException e) { e.printStackTrace(); } } } if (MessageFactoryImpl.getDefaultServerHeader() != null) { newResponse.setHeader(MessageFactoryImpl.getDefaultServerHeader()); } if (newResponse.getStatusCode() == 100) { // Trying is never supposed to have the tag parameter set. newResponse.getTo().removeParameter("tag"); } ServerHeader server = MessageFactoryImpl.getDefaultServerHeader(); if (server != null) { newResponse.setHeader(server); } return newResponse; }
/** * 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; }
/** * Creates a default ACK SIPRequest message for this original request. Note that the defaultACK * SIPRequest does not include the content of the original SIPRequest. If responseToHeader is null * then the toHeader of this request is used to construct the ACK. Note that tag fields are just * copied from the original SIP Request. Added by Jeff Keyser. * * @param responseToHeader To header to use for this request. * @return A SIPRequest with an ACK method. */ public SIPRequest createAckRequest(To responseToHeader) { SIPRequest newRequest; Iterator headerIterator; SIPHeader nextHeader; newRequest = new SIPRequest(); newRequest.setRequestLine((RequestLine) this.requestLine.clone()); newRequest.setMethod(Request.ACK); headerIterator = getHeaders(); while (headerIterator.hasNext()) { nextHeader = (SIPHeader) headerIterator.next(); if (nextHeader instanceof RouteList) { // Ack and cancel do not get ROUTE headers. // Route header for ACK is assigned by the // Dialog if necessary. continue; } else if (nextHeader instanceof ProxyAuthorization) { // Remove proxy auth header. // Assigned by the Dialog if necessary. continue; } else if (nextHeader instanceof ContentLength) { // Adding content is responsibility of user. nextHeader = (SIPHeader) nextHeader.clone(); try { ((ContentLength) nextHeader).setContentLength(0); } catch (InvalidArgumentException e) { } } else if (nextHeader instanceof ContentType) { // Content type header is removed since // content length is 0. continue; } else if (nextHeader instanceof CSeq) { // 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". CSeq cseq = (CSeq) nextHeader.clone(); try { cseq.setMethod(Request.ACK); } catch (ParseException e) { } nextHeader = cseq; } else if (nextHeader instanceof To) { if (responseToHeader != null) { nextHeader = responseToHeader; } else { nextHeader = (SIPHeader) nextHeader.clone(); } } else if (nextHeader instanceof ContactList || nextHeader instanceof Expires) { // CONTACT header does not apply for ACK requests. continue; } else if (nextHeader instanceof ViaList) { // Bug reported by Gianluca Martinello // The ACK MUST contain a single Via header field, // and this MUST be equal to the top Via header // field of the original // request. nextHeader = (SIPHeader) ((ViaList) nextHeader).getFirst().clone(); } else { nextHeader = (SIPHeader) nextHeader.clone(); } 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()); } }