📄 responseforwarding.java
字号:
A proxy MUST NOT modify the To tag in any forwarded response to a request that contains a To tag. */ /*****************************************************************************//**************** 7. Aggregate Authorization Header Field Values ********//****************************************************************************/ /****************************************************************************//**************** 8. Record-Route ********//****************************************************************************/ // we don't modify the record-route... /*****************************************************************************//**************** 9. Forward response ********//*****************************************************************************/ /* 16.7. 9. Forward response: The proxy MUST pass the response to the server transaction associated with the response context. This will result in the response being sent to the location now indicated in the topmost Via header field value. If the server transaction is no longer available to handle the transmission, the element MUST forward the response statelessly by sending it to the server transport. The server transaction might indicate failure to send the response or signal a timeout in its state machine. These errors would be logged for diagnostic purposes as appropriate, but the protocol requires no remedial action from the proxy. */ ServerTransaction serverTransaction=transactionsMapping. getServerTransaction(clientTransaction); // For forking: if ( (response.getStatusCode() == 401 ||response.getStatusCode() == 603 ) && serverTransaction!=null ) { // check the busy or decline Vector clientsTransactionList=transactionsMapping. getClientTransactions(serverTransaction); if (clientsTransactionList!=null && clientsTransactionList.size()>1){ if (ProxyDebug.debug) ProxyDebug.println ("ResponseForwarding, forwardResponse() (STEP 9), " + "the BUSY or DECLINE corresponds to a forked call, "+ " so we drop it and wait for"+ " the others responses."); transactionsMapping. removeMapping(clientTransaction); } } // For forking: if (response.getStatusCode() == 200 && serverTransaction!=null ) { Dialog peerDialog=serverTransaction.getDialog(); Vector clientsTransactionList=transactionsMapping. getClientTransactions(serverTransaction); if (peerDialog !=null && peerDialog.getState()!=null && peerDialog.getState().equals(DialogState.CONFIRMED) && clientsTransactionList!=null && clientsTransactionList.size()>1 ) { if (ProxyDebug.debug) ProxyDebug.println ("ResponseForwarding, forwardResponse() (STEP 9), " + "the 200 OK corresponds to a forked call, " + "so we drop it and send a BYE"); Dialog dialog=clientTransaction.getDialog(); Request byeRequest = dialog.createRequest("BYE"); ClientTransaction ct= sipProvider.getNewClientTransaction (byeRequest); dialog.sendRequest(clientTransaction); if (ProxyDebug.debug) ProxyDebug.println ("ResponseForwarding, forwardResponse() (STEP 9), "+ "BYE created and sent for 200 OK (forking):\n" + byeRequest.toString()); // we have to remove the transaction from the table: transactionsMapping. removeMapping(clientTransaction); return; } else { if (serverTransaction != null) transactionsMapping.addMapping (serverTransaction,clientTransaction); } } if (serverTransaction == null) { sipProvider.sendResponse(response); if (ProxyDebug.debug) ProxyDebug.println ("ResponseForwarding, forwardResponse() (STEP 9), the "+ " response is statelessly"+ " forwarded:\n"+ response.toString()); return; } else { // we can try to modify the tags: Dialog dialog=serverTransaction.getDialog(); if (dialog!=null) { String localTag= dialog.getLocalTag(); String remoteTag= dialog.getRemoteTag(); ToHeader toHeader= (ToHeader)response.getHeader(ToHeader.NAME); FromHeader fromHeader= (FromHeader)response.getHeader(FromHeader.NAME); if (localTag!=null && remoteTag!=null) { if (dialog.isServer() ) { fromHeader.setTag(remoteTag); if (ProxyDebug.debug) ProxyDebug.println ("ResponseForwarding, forwardResponse() " + " (STEP 9), we changed the " + "toTag:"+localTag); } else { toHeader.setTag(localTag); if (ProxyDebug.debug) ProxyDebug.println ("ResponseForwarding, forwardResponse() "+ " (STEP 9), we changed the fromTag:" +remoteTag); } } } serverTransaction.sendResponse(response); if (ProxyDebug.debug) ProxyDebug.println ("ResponseForwarding, forwardResponse() (STEP 9), the "+ " response is statefully forwarded: \n" +response.toString()); } /***************************************************************************//************** 10. Generate CANCELs ********//****************************************************************************/ /* If the forwarded response was a final response, the proxy MUST generate a CANCEL request for all pending client transactions associated with this response context. A proxy SHOULD also generate a CANCEL request for all pending client transactions associated with this response context when it receives a 6xx response. A pending client transaction is one that has received a provisional response, but no final response (it is in the proceeding state) and has not had an associated CANCEL generated for it. Generating CANCEL requests is described in Section 9.1. */ if (response.getStatusCode() == 200 || (response.getStatusCode() >= 600 && response.getStatusCode()<=606) ){ Vector clientsTransactionList=transactionsMapping. getClientTransactions(serverTransaction); for ( Enumeration e = clientsTransactionList.elements(); e.hasMoreElements(); ) { ClientTransaction ctr=(ClientTransaction) e.nextElement(); if ( ctr != clientTransaction ) { TransactionState transactionState=ctr.getState(); if (transactionState==null || transactionState.getValue()== TransactionState.PROCEEDING.getValue()) { /* 9.1: The following procedures are used to construct a CANCEL request. The Request-URI, Call-ID, To, the numeric part of CSeq, and From header fields in the CANCEL request MUST be identical to those in the request being cancelled, including tags. A CANCEL constructed by a client MUST have only a single Via header field value matching the top Via value in the request being cancelled. Using the same values for these header fields allows the CANCEL to be matched with the request it cancels (Section 9.2 indicates how such matching occurs). However, the method part of the CSeq header field MUST have a value of CANCEL. This allows it to be identified and processed as a transaction in its own right (See Section 17). If the request being cancelled contains a Route header field, the CANCEL request MUST include that Route header field's values. */ Request cancelRequest =ctr.createCancel(); // Let's keep only the top most via header: ListIterator cancelViaList= cancelRequest.getHeaders(ViaHeader.NAME); cancelRequest.removeHeader(ViaHeader.NAME); cancelRequest.addHeader ((ViaHeader)cancelViaList.next()); ClientTransaction ct= sipProvider.getNewClientTransaction (cancelRequest); ct.sendRequest(); if (ProxyDebug.debug) ProxyDebug.println ("ResponseForwarding, forwardResponse()" + " (STEP 10), CANCEL created"+ " and sent for cancel the pending " + "transactions:\n" + cancelRequest.toString()); } } } } } catch (Exception ex) { if (ProxyDebug.debug) { ProxyDebug.println ("ResponseForwarding, forwardResponse(), internal error, "+ "exception raised:"); ProxyDebug.logException(ex); } } finally { if (clientTransaction != null && clientTransaction.getState().equals (TransactionState.COMPLETED)) { if (clientTransaction.getDialog() != null) { transactionsMapping = (TransactionsMapping) clientTransaction.getDialog().getApplicationData(); if (transactionsMapping != null) transactionsMapping.removeMapping(clientTransaction); } } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -