📄 responseforwarding.java
字号:
/** ************************************************************************* */ /** ************* 6. Choosing the best response ******* */ /** ************************************************************************* */ /* * A proxy MUST NOT insert a tag into the To header field of a 1xx * or 2xx response if the request did not contain one. A proxy MUST * NOT modify the tag in the To header field of a 1xx or 2xx * response. * * An element SHOULD preserve the To tag when simply forwarding a * 3-6xx response to a request that did not contain a To tag. * * 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 (logger.isDebugEnabled()) logger .debug("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 ) { // Already responded to the server transaction with an OK. if (serverTransaction.getState() == TransactionState.TERMINATED) { if (logger.isDebugEnabled()) logger .debug("ResponseForwarding, forwardResponse() (STEP 9), " + "the 200 OK corresponds to a forked call, " + "so we drop it and send a BYE"); Request byeRequest = (Request) clientTransaction .getRequest().clone(); byeRequest.setMethod(Request.BYE); ToHeader toHeader = (ToHeader) response .getHeader(ToHeader.NAME); byeRequest.setHeader((ToHeader) toHeader.clone()); ClientTransaction ct = sipProvider .getNewClientTransaction(byeRequest); ct.sendRequest(); if (logger.isDebugEnabled()) logger .debug("ResponseForwarding, forwardResponse() (STEP 9), " + "BYE created and sent for 200 OK (forking):\n" + byeRequest.toString()); return; } } if (serverTransaction == null) { sipProvider.sendResponse(response); if (logger.isDebugEnabled()) logger .debug("ResponseForwarding, forwardResponse() (STEP 9), the " + " response is statelessly" + " forwarded:\n" + response.toString()); return; } else { serverTransaction.sendResponse(response); if (logger.isDebugEnabled()) logger .debug("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) && cseqHeader.getMethod().equals("INVITE")) { 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 == TransactionState.PROCEEDING) { /* * 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 (logger.isDebugEnabled()) logger .debug("ResponseForwarding, forwardResponse()" + " (STEP 10), CANCEL created" + " and sent for cancel the pending " + "transactions:\n" + cancelRequest.toString()); } } } } } catch (Exception ex) { logger.error( "ResponseForwarding, forwardResponse(), internal error, " + "exception raised:", ex); } finally { if (clientTransaction != null && ( clientTransaction.getState().equals( TransactionState.COMPLETED) || clientTransaction.getState() == TransactionState.TERMINATED) ) { transactionsMapping = (TransactionsMapping) clientTransaction .getApplicationData(); if (transactionsMapping != null) transactionsMapping.removeMapping(clientTransaction); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -