/** * 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; }
/** * Handles a new SIP response. It finds a client transaction to handle this message. If none * exists, it sends the message directly to the superclass. * * @param responseReceived Response to handle. * @param responseMessageChannel Channel that received message. * @return A client transaction. */ protected ServerResponseInterface newSIPServerResponse( SIPResponse responseReceived, MessageChannel responseMessageChannel) { // System.out.println("response = " + responseReceived.encode()); // Iterator through all client transactions Iterator<SIPClientTransaction> transactionIterator; // Next transaction in the set SIPClientTransaction nextTransaction; // Transaction to handle this request SIPClientTransaction currentTransaction; String key = responseReceived.getTransactionId(); currentTransaction = (SIPClientTransaction) clientTransactionTable.get(key); if (currentTransaction == null || !currentTransaction.isMessagePartOfTransaction(responseReceived)) { // Loop through all server transactions synchronized (clientTransactions) { transactionIterator = clientTransactions.iterator(); currentTransaction = null; while (transactionIterator.hasNext() && currentTransaction == null) { nextTransaction = (SIPClientTransaction) transactionIterator.next(); // If this transaction should handle this request, if (nextTransaction.isMessagePartOfTransaction(responseReceived)) { // Mark this transaction as the one to // handle this message currentTransaction = nextTransaction; } } } // If no transaction exists to handle this message, if (currentTransaction == null) { // Pass the message directly to the TU return super.newSIPServerResponse(responseReceived, responseMessageChannel); } } // Set ths transaction's encapsulated response interface // from the superclass currentTransaction.setResponseInterface( super.newSIPServerResponse(responseReceived, currentTransaction)); return currentTransaction; }
protected SIPMessage reprocessFirstLine( char[] firstLine, SIPMessage sipMessage, ParseExceptionListener parseExceptionListener, byte[] msgBuffer) throws ParseException { SIPMessage message = sipMessage; char[] retval = new char[firstLine.length + 1]; System.arraycopy(firstLine, 0, retval, 0, firstLine.length); retval[firstLine.length] = '\n'; if (!new String(firstLine).startsWith(SIPConstants.SIP_VERSION_STRING)) { if (message == null) { message = new SelectiveSIPRequest(headersToParse); } try { RequestLine requestLine = new RequestLineParser(retval).parse(); ((SIPRequest) message).setRequestLine(requestLine); } catch (ParseException ex) { if (parseExceptionListener != null) try { parseExceptionListener.handleException( ex, message, RequestLine.class, new String(retval), new String(msgBuffer, "UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } else throw ex; } } else { if (message == null) { message = new SelectiveSIPResponse(headersToParse); } try { StatusLine sl = new StatusLineParser(retval).parse(); ((SIPResponse) message).setStatusLine(sl); } catch (ParseException ex) { if (parseExceptionListener != null) { try { parseExceptionListener.handleException( ex, message, StatusLine.class, new String(retval), new String(msgBuffer, "UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } else throw ex; } } return message; }
protected SIPMessage processFirstLine( char[] firstLine, ParseExceptionListener parseExceptionListener, byte[] msgBuffer) throws ParseException { SIPMessage message; char[] retval = new char[firstLine.length + 1]; System.arraycopy(firstLine, 0, retval, 0, firstLine.length); retval[firstLine.length] = '\n'; char[] sipVersionCompare = new char[7]; System.arraycopy(firstLine, 0, sipVersionCompare, 0, 7); if (!Arrays.equals(sipVersionCompare, SIP_VERSION_CHAR)) { message = new SIPRequest(); try { RequestLine requestLine = new RequestLineParser(retval).parse(); ((SIPRequest) message).setRequestLine(requestLine); } catch (ParseException ex) { if (parseExceptionListener != null) parseExceptionListener.handleException( ex, message, RequestLine.class, String.valueOf(firstLine), String.valueOf(msgBuffer)); else throw ex; } } else { message = new SIPResponse(); try { StatusLine sl = new StatusLineParser(retval).parse(); ((SIPResponse) message).setStatusLine(sl); } catch (ParseException ex) { if (parseExceptionListener != null) { parseExceptionListener.handleException( ex, message, StatusLine.class, String.valueOf(firstLine), String.valueOf(msgBuffer)); } else throw ex; } } return message; }
/** * Gets invoked by the parser as a callback on successful message parsing (i.e. no parser errors). * * @param sipMessage Message to process (this calls the application for processing the message). * <p>Jvb: note that this code is identical to TCPMessageChannel, refactor some day */ public void processMessage(SIPMessage sipMessage) throws Exception { try { if (sipMessage.getFrom() == null || sipMessage.getTo() == null || sipMessage.getCallId() == null || sipMessage.getCSeq() == null || sipMessage.getViaHeaders() == null) { if (logger.isLoggingEnabled()) { String badmsg = sipMessage.encode(); logger.logError("bad message " + badmsg); logger.logError(">>> Dropped Bad Msg"); } return; } sipMessage.setRemoteAddress(this.peerAddress); sipMessage.setRemotePort(this.getPeerPort()); sipMessage.setLocalAddress(this.getMessageProcessor().getIpAddress()); sipMessage.setLocalPort(this.getPort()); // Issue 3: https://telestax.atlassian.net/browse/JSIP-3 sipMessage.setPeerPacketSourceAddress(this.peerAddress); sipMessage.setPeerPacketSourcePort(this.peerPort); ViaList viaList = sipMessage.getViaHeaders(); // For a request // first via header tells where the message is coming from. // For response, this has already been recorded in the outgoing // message. if (sipMessage instanceof SIPRequest) { Via v = (Via) viaList.getFirst(); // the peer address and tag it appropriately. Hop hop = sipStack.addressResolver.resolveAddress(v.getHop()); this.peerProtocol = v.getTransport(); // if(peerPortAdvertisedInHeaders <= 0) { int hopPort = v.getPort(); if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { logger.logDebug( "hop port = " + hopPort + " for request " + sipMessage + " for this channel " + this + " key " + key); } if (hopPort <= 0) { // if port is 0 we assume the default port for TCP this.peerPortAdvertisedInHeaders = 5060; } else { this.peerPortAdvertisedInHeaders = hopPort; } if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { logger.logDebug( "3.Storing peerPortAdvertisedInHeaders = " + peerPortAdvertisedInHeaders + " for this channel " + this + " key " + key); } // } // may be needed to reconnect, when diff than peer address if (peerAddressAdvertisedInHeaders == null) { peerAddressAdvertisedInHeaders = hop.getHost(); if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { logger.logDebug( "3.Storing peerAddressAdvertisedInHeaders = " + peerAddressAdvertisedInHeaders + " for this channel " + this + " key " + key); } } try { if (mySock != null) { // selfrouting makes socket = null // https://jain-sip.dev.java.net/issues/show_bug.cgi?id=297 this.peerAddress = mySock.getInetAddress(); } // Check to see if the received parameter matches // the peer address and tag it appropriately. // JvB: dont do this. It is both costly and incorrect // Must set received also when it is a FQDN, regardless // whether // it resolves to the correct IP address // InetAddress sentByAddress = // InetAddress.getByName(hop.getHost()); // JvB: if sender added 'rport', must always set received boolean hasRPort = v.hasParameter(Via.RPORT); if (!hasRPort && v.getPort() != peerPort) { // https://github.com/RestComm/jain-sip/issues/79 if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { logger.logDebug( "setting rport since viaPort " + v.getPort() + " different than peerPacketSourcePort " + peerPort + " so that the response can be routed back"); } hasRPort = true; } if (hasRPort || !hop.getHost().equals(this.peerAddress.getHostAddress())) { v.setParameter(Via.RECEIVED, this.peerAddress.getHostAddress()); } // @@@ hagai // JvB: technically, may only do this when Via already // contains // rport v.setParameter(Via.RPORT, Integer.toString(this.peerPort)); } catch (java.text.ParseException ex) { InternalErrorHandler.handleException(ex); } // Use this for outgoing messages as well. if (!this.isCached && mySock != null) { // self routing makes // mySock=null // https://jain-sip.dev.java.net/issues/show_bug.cgi?id=297 this.isCached = true; int remotePort = ((java.net.InetSocketAddress) mySock.getRemoteSocketAddress()).getPort(); String key = IOHandler.makeKey(mySock.getInetAddress(), remotePort); if (this.messageProcessor instanceof NioTcpMessageProcessor) { // https://java.net/jira/browse/JSIP-475 don't use iohandler in case of NIO // communications of the socket will leak in the iohandler sockettable ((NioTcpMessageProcessor) this.messageProcessor) .nioHandler.putSocket(key, mySock.getChannel()); } else { sipStack.ioHandler.putSocket(key, mySock); } // since it can close the socket it needs to be after the mySock usage otherwise // it the socket will be disconnected and NPE will be thrown in some edge cases ((ConnectionOrientedMessageProcessor) this.messageProcessor).cacheMessageChannel(this); } } // Foreach part of the request header, fetch it and process it long receptionTime = System.currentTimeMillis(); // if (sipMessage instanceof SIPRequest) { // This is a request - process the request. SIPRequest sipRequest = (SIPRequest) sipMessage; // Create a new sever side request processor for this // message and let it handle the rest. if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { logger.logDebug("----Processing Message---"); } if (logger.isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) { sipStack.serverLogger.logMessage( sipMessage, this.getPeerHostPort().toString(), this.messageProcessor.getIpAddress().getHostAddress() + ":" + this.messageProcessor.getPort(), false, receptionTime); } // Check for reasonable size - reject message // if it is too long. if (sipStack.getMaxMessageSize() > 0 && sipRequest.getSize() + (sipRequest.getContentLength() == null ? 0 : sipRequest.getContentLength().getContentLength()) > sipStack.getMaxMessageSize()) { SIPResponse sipResponse = sipRequest.createResponse(SIPResponse.MESSAGE_TOO_LARGE); byte[] resp = sipResponse.encodeAsBytes(this.getTransport()); this.sendMessage(resp, false); throw new Exception("Message size exceeded"); } String sipVersion = ((SIPRequest) sipMessage).getRequestLine().getSipVersion(); if (!sipVersion.equals("SIP/2.0")) { SIPResponse versionNotSupported = ((SIPRequest) sipMessage) .createResponse(Response.VERSION_NOT_SUPPORTED, "Bad SIP version " + sipVersion); this.sendMessage(versionNotSupported.encodeAsBytes(this.getTransport()), false); throw new Exception("Bad version "); } String method = ((SIPRequest) sipMessage).getMethod(); String cseqMethod = ((SIPRequest) sipMessage).getCSeqHeader().getMethod(); if (!method.equalsIgnoreCase(cseqMethod)) { SIPResponse sipResponse = sipRequest.createResponse(SIPResponse.BAD_REQUEST); byte[] resp = sipResponse.encodeAsBytes(this.getTransport()); this.sendMessage(resp, false); throw new Exception("Bad CSeq method" + sipMessage + " method " + method); } // Stack could not create a new server request interface. // maybe not enough resources. ServerRequestInterface sipServerRequest = sipStack.newSIPServerRequest(sipRequest, this); if (sipServerRequest != null) { try { sipServerRequest.processRequest(sipRequest, this); } finally { if (sipServerRequest instanceof SIPTransaction) { SIPServerTransaction sipServerTx = (SIPServerTransaction) sipServerRequest; if (!sipServerTx.passToListener()) ((SIPTransaction) sipServerRequest).releaseSem(); } } } else { if (sipStack.sipMessageValve == null) { // Allow message valves to nullify messages without error SIPResponse response = sipRequest.createResponse(Response.SERVICE_UNAVAILABLE); RetryAfter retryAfter = new RetryAfter(); // Be a good citizen and send a decent response code back. try { retryAfter.setRetryAfter((int) (10 * (Math.random()))); response.setHeader(retryAfter); this.sendMessage(response); } catch (Exception e) { // IGNore } if (logger.isLoggingEnabled()) logger.logWarning("Dropping message -- could not acquire semaphore"); } } } else { SIPResponse sipResponse = (SIPResponse) sipMessage; // JvB: dont do this // if (sipResponse.getStatusCode() == 100) // sipResponse.getTo().removeParameter("tag"); try { sipResponse.checkHeaders(); } catch (ParseException ex) { if (logger.isLoggingEnabled()) logger.logError("Dropping Badly formatted response message >>> " + sipResponse); return; } // This is a response message - process it. // Check the size of the response. // If it is too large dump it silently. if (sipStack.getMaxMessageSize() > 0 && sipResponse.getSize() + (sipResponse.getContentLength() == null ? 0 : sipResponse.getContentLength().getContentLength()) > sipStack.getMaxMessageSize()) { if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) logger.logDebug("Message size exceeded"); return; } ServerResponseInterface sipServerResponse = sipStack.newSIPServerResponse(sipResponse, this); if (sipServerResponse != null) { try { if (sipServerResponse instanceof SIPClientTransaction && !((SIPClientTransaction) sipServerResponse).checkFromTag(sipResponse)) { if (logger.isLoggingEnabled()) logger.logError("Dropping response message with invalid tag >>> " + sipResponse); return; } sipServerResponse.processResponse(sipResponse, this); } finally { if (sipServerResponse instanceof SIPTransaction && !((SIPTransaction) sipServerResponse).passToListener()) { // Note that the semaphore is released in event // scanner if the // request is actually processed by the Listener. ((SIPTransaction) sipServerResponse).releaseSem(); } } } else { logger.logWarning( "Application is blocked -- could not acquire semaphore -- dropping response"); } } } finally { } }
/** * Return a formatted message to the client. We try to re-connect with the peer on the other end * if possible. * * @param sipMessage Message to send. * @throws IOException If there is an error sending the message */ public void sendMessage(final SIPMessage sipMessage) throws IOException { if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG) && !sipMessage.isNullRequest()) { logger.logDebug( "sendMessage:: " + sipMessage.getFirstLine() + " cseq method = " + sipMessage.getCSeq().getMethod()); } for (MessageProcessor messageProcessor : getSIPStack().getMessageProcessors()) { if (messageProcessor.getIpAddress().getHostAddress().equals(this.getPeerAddress()) && messageProcessor.getPort() == this.getPeerPort() && messageProcessor.getTransport().equalsIgnoreCase(this.getPeerProtocol())) { Runnable processMessageTask = new Runnable() { public void run() { try { processMessage((SIPMessage) sipMessage.clone()); } catch (Exception ex) { if (logger.isLoggingEnabled(ServerLogger.TRACE_ERROR)) { logger.logError("Error self routing message cause by: ", ex); } } } }; getSIPStack().getSelfRoutingThreadpoolExecutor().execute(processMessageTask); if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) logger.logDebug("Self routing message"); return; } } byte[] msg = sipMessage.encodeAsBytes(this.getTransport()); long time = System.currentTimeMillis(); // need to store the peerPortAdvertisedInHeaders in case the response has an rport (ephemeral) // that failed to retry on the regular via port // for responses, no need to store anything for subsequent requests. if (peerPortAdvertisedInHeaders <= 0) { if (sipMessage instanceof SIPResponse) { SIPResponse sipResponse = (SIPResponse) sipMessage; Via via = sipResponse.getTopmostVia(); if (via.getRPort() > 0) { if (via.getPort() <= 0) { // if port is 0 we assume the default port for TCP this.peerPortAdvertisedInHeaders = 5060; } else { this.peerPortAdvertisedInHeaders = via.getPort(); } if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { logger.logDebug( "1.Storing peerPortAdvertisedInHeaders = " + peerPortAdvertisedInHeaders + " for via port = " + via.getPort() + " via rport = " + via.getRPort() + " and peer port = " + peerPort + " for this channel " + this + " key " + key); } } } } // JvB: also retry for responses, if the connection is gone we should // try to reconnect this.sendMessage(msg, sipMessage instanceof SIPRequest); // message was sent without any exception so let's set set port and // address before we feed it to the logger sipMessage.setRemoteAddress(this.peerAddress); sipMessage.setRemotePort(this.peerPort); sipMessage.setLocalAddress(this.getMessageProcessor().getIpAddress()); sipMessage.setLocalPort(this.getPort()); if (logger.isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) logMessage(sipMessage, peerAddress, peerPort, time); }
/** * Actually proces the parsed message. * * @param sipMessage */ public void processMessage(SIPMessage sipMessage) { if (sipMessage instanceof SIPRequest) { SIPRequest sipRequest = (SIPRequest) sipMessage; // This is a request - process it. // So far so good -- we will commit this message if // all processing is OK. if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) { this.sipStack.serverLogger.logMessage( sipMessage, this.getPeerHostPort().toString(), this.getHost() + ":" + this.myPort, false, receptionTime); } final ServerRequestInterface sipServerRequest = sipStack.newSIPServerRequest(sipRequest, this); // Drop it if there is no request returned if (sipServerRequest == null) { if (sipStack.isLoggingEnabled()) { this.sipStack .getStackLogger() .logWarning("Null request interface returned -- dropping request"); } return; } if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) this.sipStack .getStackLogger() .logDebug("About to process " + sipRequest.getFirstLine() + "/" + sipServerRequest); try { sipServerRequest.processRequest(sipRequest, this); } finally { if (sipServerRequest instanceof SIPTransaction) { SIPServerTransaction sipServerTx = (SIPServerTransaction) sipServerRequest; if (!sipServerTx.passToListener()) { ((SIPTransaction) sipServerRequest).releaseSem(); } } } if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) this.sipStack .getStackLogger() .logDebug("Done processing " + sipRequest.getFirstLine() + "/" + sipServerRequest); // So far so good -- we will commit this message if // all processing is OK. } else { // Handle a SIP Reply message. SIPResponse sipResponse = (SIPResponse) sipMessage; try { sipResponse.checkHeaders(); } catch (ParseException ex) { if (sipStack.isLoggingEnabled()) sipStack .getStackLogger() .logError("Dropping Badly formatted response message >>> " + sipResponse); return; } ServerResponseInterface sipServerResponse = sipStack.newSIPServerResponse(sipResponse, this); if (sipServerResponse != null) { try { if (sipServerResponse instanceof SIPClientTransaction && !((SIPClientTransaction) sipServerResponse).checkFromTag(sipResponse)) { if (sipStack.isLoggingEnabled()) sipStack .getStackLogger() .logError("Dropping response message with invalid tag >>> " + sipResponse); return; } sipServerResponse.processResponse(sipResponse, this); } finally { if (sipServerResponse instanceof SIPTransaction && !((SIPTransaction) sipServerResponse).passToListener()) ((SIPTransaction) sipServerResponse).releaseSem(); } // Normal processing of message. } else { if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { this.sipStack.getStackLogger().logDebug("null sipServerResponse!"); } } } }
/** * 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. * * @param statusCode Status code for the response. Reason phrase is generated. * @return A SIPResponse with the status and reason supplied, and a copy of all the original * headers from this request. */ public SIPResponse createResponse(int statusCode) { String reasonPhrase = SIPResponse.getReasonPhrase(statusCode); return this.createResponse(statusCode, reasonPhrase); }
/** * Gets invoked by the parser as a callback on successful message parsing (i.e. no parser errors). * * @param sipMessage Mesage to process (this calls the application for processing the message). */ public void processMessage(SIPMessage sipMessage) throws Exception { try { if (sipMessage.getFrom() == null || // sipMessage.getFrom().getTag() == null || sipMessage.getTo() == null || sipMessage.getCallId() == null || sipMessage.getCSeq() == null || sipMessage.getViaHeaders() == null) { String badmsg = sipMessage.encode(); if (LogWriter.needsLogging) { stack.logWriter.logMessage("bad message " + badmsg); stack.logWriter.logMessage(">>> Dropped Bad Msg"); } stack.logBadMessage(badmsg); return; } ViaList viaList = sipMessage.getViaHeaders(); // For a request // first via header tells where the message is coming from. // For response, this has already been recorded in the outgoing // message. if (sipMessage instanceof SIPRequest) { Via v = (Via) viaList.first(); if (v.hasPort()) { this.peerPort = v.getPort(); } else this.peerPort = 5061; this.peerProtocol = v.getTransport(); try { this.peerAddress = mySock.getInetAddress(); // Check to see if the received parameter matches // the peer address and tag it appropriately. // Bug fix by [email protected] // Should record host address not host name // bug fix by Joost Yervante Damand if (!v.getSentBy().getInetAddress().equals(this.peerAddress)) { v.setParameter(Via.RECEIVED, this.peerAddress.getHostAddress()); // @@@ hagai v.setParameter(Via.RPORT, new Integer(this.peerPort).toString()); } } catch (java.net.UnknownHostException ex) { // Could not resolve the sender address. if (LogWriter.needsLogging) { stack.logWriter.logMessage("Rejecting message -- could not resolve Via Address"); } return; } catch (java.text.ParseException ex) { InternalErrorHandler.handleException(ex); } // Use this for outgoing messages as well. if (!this.isCached) { ((TLSMessageProcessor) this.messageProcessor).cacheMessageChannel(this); this.isCached = true; String key = IOHandler.makeKey(mySock.getInetAddress(), this.peerPort); stack.ioHandler.putSocket(key, mySock); } } // Foreach part of the request header, fetch it and process it long receptionTime = System.currentTimeMillis(); // if (sipMessage instanceof SIPRequest) { // This is a request - process the request. SIPRequest sipRequest = (SIPRequest) sipMessage; // Create a new sever side request processor for this // message and let it handle the rest. if (LogWriter.needsLogging) { stack.logWriter.logMessage("----Processing Message---"); } // Check for reasonable size - reject message // if it is too long. if (stack.getMaxMessageSize() > 0 && sipRequest.getSize() + (sipRequest.getContentLength() == null ? 0 : sipRequest.getContentLength().getContentLength()) > stack.getMaxMessageSize()) { SIPResponse sipResponse = sipRequest.createResponse(SIPResponse.MESSAGE_TOO_LARGE); byte[] resp = sipResponse.encodeAsBytes(); this.sendMessage(resp, false); throw new Exception("Message size exceeded"); } ServerRequestInterface sipServerRequest = stack.newSIPServerRequest(sipRequest, this); sipServerRequest.processRequest(sipRequest, this); if (this.stack.serverLog.needsLogging(ServerLog.TRACE_MESSAGES)) { if (sipServerRequest.getProcessingInfo() == null) { stack.serverLog.logMessage( sipMessage, sipRequest.getViaHost() + ":" + sipRequest.getViaPort(), stack.getHostAddress() + ":" + stack.getPort(this.getTransport()), false, receptionTime); } else { this.stack.serverLog.logMessage( sipMessage, sipRequest.getViaHost() + ":" + sipRequest.getViaPort(), stack.getHostAddress() + ":" + stack.getPort(this.getTransport()), sipServerRequest.getProcessingInfo(), false, receptionTime); } } } else { SIPResponse sipResponse = (SIPResponse) sipMessage; // This is a response message - process it. // Check the size of the response. // If it is too large dump it silently. if (stack.getMaxMessageSize() > 0 && sipResponse.getSize() + (sipResponse.getContentLength() == null ? 0 : sipResponse.getContentLength().getContentLength()) > stack.getMaxMessageSize()) { if (LogWriter.needsLogging) this.stack.logWriter.logMessage("Message size exceeded"); return; } ServerResponseInterface sipServerResponse = stack.newSIPServerResponse(sipResponse, this); sipServerResponse.processResponse(sipResponse, this); } } finally { } }
/** * Make a clone (deep copy) of this object. * * @return a deep copy of this object. */ public Object clone() { SIPResponse retval = (SIPResponse) super.clone(); if (this.statusLine != null) retval.statusLine = (StatusLine) this.statusLine.clone(); return retval; }
/** * @param originalRequestEvent * @param response * @param serviceUnit */ @Override public void sendResponse( RequestEvent originalRequestEvent, Response response, ServiceUnit serviceUnit, String toTag) { /** Here we need to do some specific handling specific to the type of responses being sent. */ /** * If it is a 180 RINGING response, then we need to set the To tag to the same to tag generated * when creating the associated B2BSession and B2BDialog. */ if (isDialogCreating(response.getStatusCode())) { logger.fine("Sending a ringing response..."); /** Copy the Local Tag from the B2BDialog to the SipResponse */ logger.info("Setting the To Dialog of the response to be sent to : " + toTag); SIPResponse sipResponse = (SIPResponse) response; sipResponse.setToTag(toTag); } logger.info( "Sending Response for the request associated with ServiceUnit: " + serviceUnit.getName()); /** Conveying the response sending to the UserAgent */ logger.info("Sending Response: " + response.getReasonPhrase()); Dialog sipDialog = userAgent.sendResponse(originalRequestEvent, response, serviceUnit); if (sipDialog == null) { logger.info( "The sent response " + response.getReasonPhrase() + " did not resulted in any dialog..."); } else { logger.info( "The sent response " + response.getReasonPhrase() + " has created a new Dialog with ID: " + sipDialog.getDialogId()); } /** * Set the underlying SIP Dialog of the B2BDialog for Dialog creating responses as well as the * local seq number and the current state of the dialog. */ if (isDialogCreating(response.getStatusCode())) { B2BSession b2BSessions[] = RuntimeComponentContext.getInstance().getB2BSessions(serviceUnit.getName()); for (B2BSession b2BSession : b2BSessions) { B2BDialogImpl b2BDialogImpl = null; if (sipDialog != null) { b2BDialogImpl = (B2BDialogImpl) b2BSession.getB2BDialog(sipDialog.getDialogId(), true, null); } if (b2BDialogImpl != null) { logger.info( "Setting the underlying SIP Dialog property of the B2BDialog: " + b2BDialogImpl.getDialogId()); b2BDialogImpl.setUnderlyingSipDialog(sipDialog); b2BDialogImpl.setLocalSeqNumber(sipDialog.getLocalSeqNumber()); b2BDialogImpl.setState(sipDialog.getState().toString()); logger.info( "Setting the Dialog status with ID: " + b2BDialogImpl.getDialogId() + " to " + sipDialog.getState().toString()); break; } else { logger.info("Unable to locate a B2BDialog with ID " + sipDialog.getDialogId()); } } } }