FileDocCategorySizeDatePackage
NistSipMessageHandlerImpl.javaAPI DocphoneME MR2 API (J2ME)25378Wed May 02 18:00:42 BST 2007gov.nist.siplite

NistSipMessageHandlerImpl

public class NistSipMessageHandlerImpl extends Object implements SIPServerRequestInterface, SIPServerResponseInterface
An adapter class from the JAIN implementation objects to the NIST-SIP stack. This is the class that is instantiated by the NistSipMessageFactory to create a new SIPServerRequest or SIPServerResponse. Note that this is not part of the JAIN-SIP spec (it does not implement a JAIN-SIP interface). This is part of the glue that ties together the NIST-SIP stack and event model with the JAIN-SIP stack. Implementors of JAIN services need not concern themselves with this class.
version
JAIN-SIP-1.1 This code is in the public domain.

Fields Summary
protected Transaction
transactionChannel
Current transaction channel.
protected MessageChannel
rawMessageChannel
Raw message channel.
protected ListeningPoint
listeningPoint
Current listening filter.
Constructors Summary
Methods Summary
public java.lang.StringgetProcessingInfo()
Just a placeholder. This is called from the stack for message logging. Auxiliary processing information can be passed back to be written into the log file.

return
auxiliary information that we may have generated during the message processing which is retrieved by the message logger. (Always returns null)

        return null;
    
public MessageChannelgetRequestChannel()
Gets the sender channel.

return
the request channel

        return this.transactionChannel;
    
public MessageChannelgetResponseChannel()
Gets the channel if we want to initiate a new transaction to the sender of a response.

return
a message channel that points to the place from where we got the response.

        if (this.transactionChannel != null)
            return this.transactionChannel;
        else return this.rawMessageChannel;
    
public voidprocessRequest(Request sipRequest, MessageChannel incomingMessageChannel)
Process a request.

param
sipRequest the request to be processed
param
incomingMessageChannel the inbound message connection
exception
SIPServerException is thrown when there is an error processing the request.

        // Generate the wrapper JAIN-SIP object.
        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
                "PROCESSING INCOMING REQUEST " + sipRequest.getFirstLine());
        }
        this.rawMessageChannel = incomingMessageChannel;
        
        SipStack sipStack = (SipStack) transactionChannel.getSIPStack();
        
        /*
         * What if the listeningPoint of the incomingMessagechannel different
         * than the one that set during initialization in
         * NistSipMesageFactoryImpl?
         * So, initialize it explicitely for the incomingMessageChannel
         */
        listeningPoint =
              incomingMessageChannel.getMessageProcessor().getListeningPoint();
        if (listeningPoint == null) {
            if (Logging.REPORT_LEVEL <= Logging.WARNING) {
                Logging.report(Logging.WARNING, LogChannels.LC_JSR180,
                    "Dropping message: No listening point registered!");
            }
            return;
        }
        
        SipProvider sipProvider = listeningPoint.getProvider();
        
        if (sipProvider == null)  {
            if (Logging.REPORT_LEVEL <= Logging.WARNING) {
                Logging.report(Logging.WARNING, LogChannels.LC_JSR180,
                    "No provider - dropping !!");
            }
            return;
        }

        // SipListener sipListener = sipProvider.sipListener;
        Transaction transaction = transactionChannel;
        
        // Look for the registered SIPListener for the message channel.
        synchronized (sipProvider) {
            String dialogId = sipRequest.getDialogId(true);
            Dialog dialog = sipStack.getDialog(dialogId);
            final ServerTransaction requestTransaction =
                    (ServerTransaction) sipRequest.getTransaction();
            if (null == requestTransaction.getDialog()) {
                requestTransaction.setDialog(dialog);
            }
            if (sipRequest.getMethod().equals(Request.ACK)) {
                // Could not find transaction. Generate an event
                // with a null transaction identifier.
                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                    Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
                        "Processing ACK for dialog " + dialog);
                }
                
                if (dialog == null) {
                    if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                        Logging.report(Logging.INFORMATION,
                            LogChannels.LC_JSR180,
                            "Dialog does not exist "
                            + sipRequest.getFirstLine() +
                            " isServerTransaction = " + true);
                    }

                    transaction =
                            sipStack.findTransaction(sipRequest, true);
                } else if (dialog.getLastAck() != null &&
                        dialog.getLastAck().equals(sipRequest)) {
                    if (sipStack.isRetransmissionFilterActive()) {
                        dialog.ackReceived(sipRequest);
                        transaction.setDialog(dialog);
                        
                        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                            Logging.report(Logging.INFORMATION,
                                LogChannels.LC_JSR180,
                                "Retransmission Filter enabled -" 
                                + " dropping Ack retransmission");
                        }
                        
                        // filter out retransmitted acks if
                        // retransmission filter is enabled.
                        return;
                    }
                    
                    if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                        Logging.report(Logging.INFORMATION,
                            LogChannels.LC_JSR180,
                            "ACK retransmission for 2XX "
                            + "response "
                            + "Sending ACK to the TU");
                    }
                } else {
                    //	This could be a re-invite processing.
                    // check to see if the ack matches with the last
                    // transaction.
                    
                    Transaction tr = dialog.getLastTransaction();
                    Response sipResponse = tr.getLastResponse();
                    
                    if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                        Logging.report(Logging.INFORMATION,
                            LogChannels.LC_JSR180, "TRANSACTION:" + tr);
                    }
                    
                    if (tr instanceof ServerTransaction &&
                            sipResponse != null &&
                            sipResponse.getStatusCode() / 100 == 2
                            && sipResponse.getCSeqHeader().getSequenceNumber()
                            == sipRequest.getCSeqHeader().getSequenceNumber()) {
                        transaction.setDialog(dialog);
                        dialog.ackReceived(sipRequest);
                        
                        if (sipStack.isRetransmissionFilterActive() &&
                                tr.isAckSeen()) {
                            if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                                Logging.report(Logging.INFORMATION,
                                    LogChannels.LC_JSR180,
                                    "ACK retransmission for"
                                    + " 2XX response --- "
                                    + "Dropping ");
                            }
                            return;
                        } else {
                            // record that we already saw an ACK for
                            // this transaction.
                            tr.setAckSeen();
                            if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                                Logging.report(Logging.INFORMATION,
                                    LogChannels.LC_JSR180,
                                    "ACK retransmission for 2XX "
                                    + "response --- "
                                    + "sending to TU ");
                            }
                        }
                        
                    } else {
                        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                            Logging.report(Logging.INFORMATION,
                                LogChannels.LC_JSR180,
                                "ACK retransmission for non"
                                + " 2XX response "
                                + "Discarding ACK");
                        }
                        
                        // Could not find a transaction.
                        if (tr == null) {
                            if (Logging.REPORT_LEVEL <= Logging.WARNING) {
                                Logging.report(Logging.WARNING,
                                    LogChannels.LC_JSR180,
                                    "Could not find transaction ACK dropped");
                            }
                            return;
                        }
                        
                        transaction = tr;
                        if (transaction instanceof ClientTransaction) {
                            if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                                Logging.report(Logging.INFORMATION,
                                    LogChannels.LC_JSR180,
                                    "Dropping late ACK");
                            }
                            return;
                        }
                    }
                }
            } else if (sipRequest.getMethod().equals(Request.BYE)) {
                transaction = this.transactionChannel;
                // If the stack has not mapped this transaction because
                // of sequence number problem then just drop the BYE
                if (transaction != null &&
                       ((ServerTransaction)transaction).isTransactionMapped()) {
                    // Get the dialog identifier for the bye request.
                    if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                        Logging.report(Logging.INFORMATION,
                            LogChannels.LC_JSR180, "dialogId = " + dialogId);
                    }
                    
                    // Find the dialog identifier in the SIP stack and
                    // mark it for garbage collection.
                    if (dialog != null) {
                        // Remove dialog marks all
                        dialog.addTransaction(transaction);
                    } else {
                        dialogId = sipRequest.getDialogId(false);
                        
                        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                            Logging.report(Logging.INFORMATION,
                                LogChannels.LC_JSR180,
                                "dialogId = " + dialogId);
                        }
                        
                        dialog = sipStack.getDialog(dialogId);
                        
                        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                            Logging.report(Logging.INFORMATION,
                            LogChannels.LC_JSR180, "dialog = " + dialog);
                        }
                        
                        if (dialog != null) {
                            dialog.addTransaction(transaction);
                        } else {
                            transaction = null;
                            // pass up to provider for
                            // stateless handling.
                        }
                    }
                } else if (transaction != null)  {
                    // This is an out of sequence BYE
                    // transaction was allocated but
                    // not mapped to the stack so
                    // just discard it.
                    if (dialog != null) {
                        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                            Logging.report(Logging.INFORMATION,
                                LogChannels.LC_JSR180,
                                "Dropping out of sequence BYE");
                        }
                        return;
                    } else transaction = null;
                }
                // note that the transaction may be null (which
                // happens when no dialog for the bye was fund.
            } else if (sipRequest.getRequestLine().getMethod().equals
                    (Request.CANCEL)) {
                
                // The ID refers to a previously sent
                // INVITE therefore it refers to the
                // server transaction table.
                // Find the transaction to cancel.
                // Send a 487 for the cancel to inform the
                // other side that we've seen it but do not send the
                // request up to the application layer.
                
                // Get rid of the CANCEL transaction -- we pass the
                // transaciton we are trying to cancel up to the TU.
                
                // Antonis Karydas: Suggestion
                // 'transaction' here refers to the transaction to
                // be cancelled. Do not change
                // it's state because of the CANCEL.
                // Wait, instead for the 487 from TU.
                // transaction.setState(Transaction.TERMINATED_STATE);
                
                ServerTransaction serverTransaction =
                        (ServerTransaction)
                        sipStack.findCancelTransaction(sipRequest, true);
                
                // Generate an event
                // with a null transaction identifier.
                if (serverTransaction == null) {
                    // Could not find the invite transaction.
                    if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                        Logging.report(Logging.INFORMATION,
                            LogChannels.LC_JSR180,
                            "transaction "
                            + " does not exist "
                            + sipRequest.getFirstLine()
                            + "isServerTransaction = "
                            + true);
                    }
                    transaction = null;
                } else {
                    transaction = serverTransaction;
                }
            }
            
            
            if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
                    "-----------------");
                Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
                    sipRequest.toString());
            }
            
            if (dialog != null &&
                    transaction != null &&
                    ! sipRequest.getMethod().equals(Request.BYE) &&
                    ! sipRequest.getMethod().equals(Request.CANCEL) &&
                    ! sipRequest.getMethod().equals(Request.ACK)) {
                // already dealt with bye above.
                // Note that route updates are only effective until
                // Dialog is in the confirmed state.
                if (dialog.getRemoteSequenceNumber() >=
                        sipRequest.getCSeqHeader().getSequenceNumber()) {
                    if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                        Logging.report(Logging.INFORMATION,
                            LogChannels.LC_JSR180,
                            "Dropping out of sequence message " +
                            dialog.getRemoteSequenceNumber() +
                            " "  + sipRequest.getCSeqHeader());
                    }
                    
                    return;
                }
                
                dialog.addTransaction(transaction);
                dialog.addRoute(sipRequest);
            }
            
            
            RequestEvent sipEvent;
            
            if (dialog == null && sipRequest.getMethod().equals
                    (Request.NOTIFY)) {
                ClientTransaction ct =
                        sipStack.findSubscribeTransaction(sipRequest);
                // From RFC 3265
                // If the server transaction cannot be found or if it
                // aleady has a dialog attached to it then just assign the
                // notify to this dialog and pass it up.
                if (ct != null) {
                    transaction.setDialog(ct.getDialog());
                    if (ct.getDialog().getState() == Dialog.INITIAL_STATE) {
                        sipEvent = new RequestEvent
                                (sipProvider, null, (Request) sipRequest);
                    } else {
                        sipEvent = new RequestEvent
                                (sipProvider,
                                (ServerTransaction)transaction,  sipRequest);
                    }
                } else {
                    // Got a notify out of the blue - just pass it up
                    // for stateless handling by the application.
                    sipEvent = new RequestEvent
                            (sipProvider, null,  sipRequest);
                }
                
            } else {
                // For a dialog creating event - set the transaction to null.
                // The listener can create the dialog if needed.
                if (transaction != null &&
                        ((ServerTransaction) transaction).isTransactionMapped())
                    sipEvent = new RequestEvent(sipProvider,
                            (ServerTransaction) transaction,
                            sipRequest);
                else sipEvent = new RequestEvent
                        (sipProvider, null,  sipRequest);
            }
            sipProvider.handleEvent(sipEvent,  transaction);
        }
        
    
public voidprocessResponse(Response sipResponse, MessageChannel incomingMessageChannel)
Process the response.

param
sipResponse the response message
param
incomingMessageChannel message channel on which the response is received.
exception
SIPServerException is thrown when there is an error processing the response

        try {
            if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
                    "PROCESSING INCOMING RESPONSE" + sipResponse.encode());
            }

            /*
             * What if the listeningPoint of the incomingMessagechannel
             * different than the one that set during initialization in
             * NistSipMesageFactoryImpl?
             * So, initialize it explicitely for the incomingMessageChannel.
             */
            listeningPoint =
               incomingMessageChannel.getMessageProcessor().getListeningPoint();

            if (listeningPoint == null) {
                if (Logging.REPORT_LEVEL <= Logging.WARNING) {
                    Logging.report(Logging.WARNING, LogChannels.LC_JSR180,
                        "Dropping message: No listening point registered!");
                }
                return;
            }

            Transaction transaction = this.transactionChannel;
            SipProvider sipProvider = listeningPoint.getProvider();
            
            if (sipProvider == null) {
                if (Logging.REPORT_LEVEL <= Logging.WARNING) {
                    Logging.report(Logging.WARNING, LogChannels.LC_JSR180,
                        "Dropping message:  no provider");
                }
                return;
            }
            
            SipStack sipStack = sipProvider.sipStack;
            
            if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
                    "Transaction = " + transaction);
            }
            
            if (this.transactionChannel == null) {
                String dialogId = sipResponse.getDialogId(false);
                Dialog dialog = sipStack.getDialog(dialogId);

                //  Have a dialog but could not find transaction.
                if (sipProvider.sipListener == null) {
                    return;
                } else if (dialog != null) {
                    if (sipResponse.getStatusCode() != Response.OK) {
                        return;
                    } else if (sipStack.isRetransmissionFilterActive()) {
                        // 200  retransmission for the final response.
                        if (sipResponse.getCSeqHeader().equals(
                                dialog.getFirstTransaction().getRequest().
                                    getHeader(Header.CSEQ))) {
                            dialog.resendAck();
                            return;
                        }
                    }
                }
                
                // long receptionTime = System.currentTimeMillis();
                // Pass the response up to the application layer to handle
                // statelessly.
                
                // Dialog is null so this is handled statelessly
                ResponseEvent sipEvent =
                      new ResponseEvent(sipProvider, null, sipResponse);
                sipProvider.handleEvent(sipEvent, transaction);
                // transaction.logResponse(sipResponse,
                //       receptionTime,"Retransmission");
                return;
            }
            
            this.rawMessageChannel = incomingMessageChannel;
            
            String method = sipResponse.getCSeqHeader().getMethod();
            // Retrieve the client transaction for which we are getting
            // this response.
            ClientTransaction clientTransaction =
                    (ClientTransaction) this.transactionChannel;
            
            Dialog dialog = null;
            if (transaction != null) {
                dialog =  transaction.getDialog();
                
                if (Logging.REPORT_LEVEL <= Logging.INFORMATION &&
                        dialog == null) {
                    Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
                        "dialog not found for " + sipResponse.getFirstLine());
                }
            }
            
            // SipListener sipListener = sipProvider.sipListener;
            
            ResponseEvent responseEvent = new ResponseEvent
                    (sipProvider, (ClientTransaction)transaction, sipResponse);
            sipProvider.handleEvent(responseEvent, transaction);
        } catch (NullPointerException ex) {
            if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
                    "null ptr");
                ex.printStackTrace();
            }
        }