session.java
来自「Logica lastest SMPP API」· Java 代码 · 共 1,451 行 · 第 1/4 页
JAVA
1,451 行
* the command id says, that the PDU is generic nack.<br> * If the command id is not generic nack, then we received * incorrect pdu as the sequence numbers match, so we send generic nack * back to the smsc. * if the command id's match, then the <code>pdu</code> is returned. * @param pdu the received PDU which should be a response * @param expResponse the response we expected from smsc * @return either the received PDU or expected response transformed to * generic nack. * @see #send(Request,boolean) */ private Response checkResponse(PDU pdu, Response expResponse) throws ValueNotSetException, TimeoutException, IOException { Response response = null; debug.write(DSESS,"checking response if it's what we expected."); if (pdu.getCommandId() != expResponse.getCommandId()) { debug.write(DSESS,"Got different response than expected " + expResponse.debugString()); if (pdu.getCommandId() == Data.GENERIC_NACK) { // it's brutal, but it's necessary // we transform the response object to carry generic nack debug.write(DSESS,"Got generic nack. What could we do wrong?"); expResponse.setCommandId(Data.GENERIC_NACK); expResponse.setCommandLength(pdu.getCommandLength()); expResponse.setCommandStatus(pdu.getCommandStatus()); expResponse.setSequenceNumber(pdu.getSequenceNumber()); response = expResponse; } else { debug.write(DSESS,"invalid command id - sending gnack"); safeGenericNack(Data.ESME_RINVCMDID,response.getSequenceNumber()); response = null; } } else { // if the commandId is same as of the expected response's command id, // then the pdu must be Response as well response = (Response)pdu; } return response; } /** * Sends a generic acknowledge with given comand status and sequence number * and catches andy <code>SmppException</code>. * @param commandStatus command status to report * @param sequenceNumber to allow the other party to match the generic ack with * their sent request * @exception IOException if there is a comms error */ private void safeGenericNack(int commandStatus, int sequenceNumber) throws IOException { try { genericNack(commandStatus,sequenceNumber); } catch (SmppException e) { debug.write("Ignoring unexpected SmppException caught sending generic nack."); event.write(e, "Ignoring unexpected exception caught sending generic nack."); } } /** * Sets the state of the session. * It's private as it's only for use by the methods of the session. * @param state the new state of the session * @see #checkState(int) * @see #checkState(PDU) * @see WrongSessionStateException */ private void setState(int state) { this.state = state; } /** * Returns the current state of the session. * It's public to allow the user to check the state of the session if necessary. * @return the current state of the session * @see #checkState(int) * @see #checkState(PDU) * @see WrongSessionStateException */ public int getState() { return state; } /** * Enables checking if the session allows certain operation in the current state. */ public void enableStateChecking() { this.stateChecking = true; } /** * Disables checking if the session allows certain operation in the current state. */ public void disableStateChecking() { this.stateChecking = false; } /** * Checks if the session is in the state which is required by the parameter. * If not, then exception <code>WrongSessionStateException</code> is thrown. * Note that the states are bit values in integer, so there can be a "set" * of states required, the session must be in one of the states required. * The checking can be turned off, see * <a href="#disableStateChecking()">disableStateChecking</a>. * @param requestedState the state(s) in which the session is expected to be; if it * is not, then exception is thrown * @throws WrongSessionStateException if the session is not in the state * required * @see WrongSessionStateException */ public void checkState(int requestedState) throws WrongSessionStateException { if (stateChecking) { debug.write(DSESS, "checking state current=0x" + Integer.toHexString(state) + " requested esme=0x" + Integer.toHexString(requestedState)); if ((state & requestedState) == 0) { throw new WrongSessionStateException(type,requestedState,state); } } } /** * Checks if the session's state allows sending the PDU provided. * If not, then exception <code>WrongSessionStateException</code> is thrown. * For each state there is only a subset of PDUs which can be sent over the * session. For example, if the session is bound as a receiver, it cannot * submit messages, but it can send enquire link, generic nack etc. * This method checks the PDU type (command id) aganst matrix of allowed states. * The checking can be turned off, see * <a href="#disableStateChecking()">disableStateChecking</a>. * @param pdu the pdu which has to be checked if it's allowed in the current * state * @throws WrongSessionStateException if the session is not in the state * required * @see #checkState(int) * @see WrongSessionStateException */ public void checkState(PDU pdu) throws WrongSessionStateException { if (stateChecking) { Hashtable pduMatrix = getStateMatrix(type); Integer commandIdInteger = new Integer(pdu.getCommandId()); Integer requestedStateInteger = pduMatrix==null ? null : (Integer)pduMatrix.get(commandIdInteger); if (requestedStateInteger != null) { checkState(requestedStateInteger.intValue()); } else { if (disallowUnknownPDU) { throw new WrongSessionStateException(); } } } } /** * Checks if the session is in the state which is required by the parameter. * Note that this method doesn't throw an exception rather it returns false * if the session is not in one of the provided states. * @param requestedState the state(s) which have to be checked * @return if the session is in on of the provided states * @see #checkState(int) */ public boolean isStateAllowed(int requestedState) { boolean stateAllowed = true; try { checkState(requestedState); } catch (WrongSessionStateException e) { stateAllowed = false; } return stateAllowed; } /** * Checks if the pdu provided is allowed in the current session state. * Note that this method doesn't throw an exception rather it returns false * if the pdu is not alloewd in the current session state. * @param pdu the pdu which has to be checked if it's allowed in the current * state * @return if the pdu is allowed to be sent in the current session state * @see #checkState(PDU) */ public boolean isPDUAllowed(PDU pdu) { boolean pduAllowed = true; try { checkState(pdu); } catch (WrongSessionStateException e) { pduAllowed = false; } return pduAllowed; } /** * Initialises state matrices for checking if PDU is allowed in a certain session * state. */ static { initialiseStateMatrix(); } /** * Initialise list containing which operations (PDUs) valid in which state. * @see #checkState(PDU) * @see #type */ private static void initialiseStateMatrix() { esmeStateMatrix = new Hashtable(); addValidState(esmeStateMatrix,Data.BIND_TRANSMITTER, STATE_CLOSED); addValidState(esmeStateMatrix,Data.BIND_TRANSMITTER_RESP, STATE_NOT_ALLOWED); addValidState(esmeStateMatrix,Data.BIND_RECEIVER, STATE_CLOSED); addValidState(esmeStateMatrix,Data.BIND_RECEIVER_RESP, STATE_NOT_ALLOWED); addValidState(esmeStateMatrix,Data.BIND_TRANSCEIVER, STATE_CLOSED); addValidState(esmeStateMatrix,Data.BIND_TRANSCEIVER_RESP, STATE_NOT_ALLOWED); addValidState(esmeStateMatrix,Data.OUTBIND, STATE_NOT_ALLOWED); addValidState(esmeStateMatrix,Data.UNBIND, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); addValidState(esmeStateMatrix,Data.UNBIND_RESP, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); addValidState(esmeStateMatrix,Data.SUBMIT_SM, STATE_TRANSMITTER | STATE_TRANSCEIVER); addValidState(esmeStateMatrix,Data.SUBMIT_SM_RESP, STATE_NOT_ALLOWED); addValidState(esmeStateMatrix,Data.SUBMIT_MULTI, STATE_TRANSMITTER | STATE_TRANSCEIVER); addValidState(esmeStateMatrix,Data.SUBMIT_MULTI_RESP, STATE_NOT_ALLOWED); addValidState(esmeStateMatrix,Data.DATA_SM, STATE_TRANSMITTER | STATE_TRANSCEIVER); addValidState(esmeStateMatrix,Data.DATA_SM_RESP, STATE_RECEIVER | STATE_TRANSCEIVER); addValidState(esmeStateMatrix,Data.DELIVER_SM, STATE_NOT_ALLOWED); addValidState(esmeStateMatrix,Data.DELIVER_SM_RESP, STATE_RECEIVER | STATE_TRANSCEIVER); addValidState(esmeStateMatrix,Data.QUERY_SM, STATE_TRANSMITTER | STATE_TRANSCEIVER); addValidState(esmeStateMatrix,Data.QUERY_SM_RESP, STATE_NOT_ALLOWED); addValidState(esmeStateMatrix,Data.CANCEL_SM, STATE_TRANSMITTER | STATE_TRANSCEIVER); addValidState(esmeStateMatrix,Data.CANCEL_SM_RESP, STATE_NOT_ALLOWED); addValidState(esmeStateMatrix,Data.REPLACE_SM, STATE_TRANSMITTER | STATE_TRANSCEIVER); addValidState(esmeStateMatrix,Data.REPLACE_SM_RESP, STATE_NOT_ALLOWED); addValidState(esmeStateMatrix,Data.ENQUIRE_LINK, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_ALWAYS); addValidState(esmeStateMatrix,Data.ENQUIRE_LINK_RESP, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_ALWAYS); addValidState(esmeStateMatrix,Data.ALERT_NOTIFICATION, STATE_NOT_ALLOWED); addValidState(esmeStateMatrix,Data.GENERIC_NACK, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_ALWAYS); mcStateMatrix = new Hashtable(); addValidState(mcStateMatrix,Data.BIND_TRANSMITTER, STATE_NOT_ALLOWED); addValidState(mcStateMatrix,Data.BIND_TRANSMITTER_RESP, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_OPENED); addValidState(mcStateMatrix,Data.BIND_RECEIVER, STATE_NOT_ALLOWED); addValidState(mcStateMatrix,Data.BIND_RECEIVER_RESP, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_OPENED); addValidState(mcStateMatrix,Data.BIND_TRANSCEIVER, STATE_NOT_ALLOWED); addValidState(mcStateMatrix,Data.BIND_TRANSCEIVER_RESP, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_OPENED); addValidState(mcStateMatrix,Data.OUTBIND, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_OPENED); addValidState(mcStateMatrix,Data.UNBIND, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); addValidState(mcStateMatrix,Data.UNBIND_RESP, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); addValidState(mcStateMatrix,Data.SUBMIT_SM, STATE_NOT_ALLOWED); addValidState(mcStateMatrix,Data.SUBMIT_SM_RESP, STATE_TRANSMITTER | STATE_TRANSCEIVER); addValidState(mcStateMatrix,Data.SUBMIT_MULTI, STATE_NOT_ALLOWED); addValidState(mcStateMatrix,Data.SUBMIT_MULTI_RESP, STATE_TRANSMITTER | STATE_TRANSCEIVER); addValidState(mcStateMatrix,Data.DATA_SM, STATE_RECEIVER | STATE_TRANSCEIVER); addValidState(mcStateMatrix,Data.DATA_SM_RESP, STATE_TRANSMITTER | STATE_TRANSCEIVER); addValidState(mcStateMatrix,Data.DELIVER_SM, STATE_RECEIVER | STATE_TRANSCEIVER); addValidState(mcStateMatrix,Data.DELIVER_SM_RESP, STATE_NOT_ALLOWED); addValidState(mcStateMatrix,Data.QUERY_SM, STATE_NOT_ALLOWED); addValidState(mcStateMatrix,Data.QUERY_SM_RESP, STATE_TRANSMITTER | STATE_TRANSCEIVER); addValidState(mcStateMatrix,Data.CANCEL_SM, STATE_NOT_ALLOWED); addValidState(mcStateMatrix,Data.CANCEL_SM_RESP, STATE_TRANSMITTER | STATE_TRANSCEIVER); addValidState(mcStateMatrix,Data.REPLACE_SM, STATE_NOT_ALLOWED); addValidState(mcStateMatrix,Data.REPLACE_SM_RESP, STATE_TRANSMITTER | STATE_TRANSCEIVER); addValidState(mcStateMatrix,Data.ENQUIRE_LINK, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_ALWAYS); addValidState(mcStateMatrix,Data.ENQUIRE_LINK_RESP, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_ALWAYS); addValidState(mcStateMatrix,Data.ALERT_NOTIFICATION, STATE_RECEIVER | STATE_TRANSCEIVER); addValidState(mcStateMatrix,Data.GENERIC_NACK, STATE_TRANSMITTER | STATE_RECEIVER | STATE_TRANSCEIVER); // STATE_ALWAYS); } /** * Adds to the matrix a set of states in which can be sent a PDU with the * provided command id. * @param matrix the matrix to add the mapping to * @param commandId the commandId of the PDU the mapping is created for * @param state the state(s) in which is the PDU valid * @see #checkState(PDU) * @see #isStateAllowed(int) */ private static void addValidState(Hashtable matrix, int commandId, int state) { matrix.put(new Integer(commandId), new Integer(state)); } /** * Returns the state matrix for the requested session type. * @see #type * @see #TYPE_ESME * @see #TYPE_MC * @see #initialiseStateMatrix() */ private static Hashtable getStateMatrix(int type) { switch (type) { case TYPE_ESME: return esmeStateMatrix; case TYPE_MC: return mcStateMatrix; default: return null; } } /** * God, I would never think that to keep unbind synchronous in * an asynchronous enviroment would be so funny. Here is the replacement * listener which encapsulates the original listener and hunts for the * unbind pdu. Good luck, you source code reader!<br> * The problem is that we want to return a response from session's unbind() * even if the session is asynchronous, i.e. all pdus from the smsc * are passed to an implementation of <code>ServerPDUEventListener</code> * event responses. We can't simply stop the asynchronicity * as there can still be some responses expected, so we need a bridge * which allows us to wait for the unbind response and still serve * the other pdus from the smsc in asynchronous manner. Thus this * encapsulating listener, which exactly does the thing. */ private class UnbindServerPDUEventListener extends SmppObject implements ServerPDUEventListener { Session session; ServerPDUEventListener origListener; Unbind unbindReq; UnbindResp expectedResp; UnbindResp unbindResp = null; public UnbindServerPDUEventListener(Session session, ServerPDUEventListener origListener, Unbind unbindReq) { this.session = session; this.origListener = origListener; this.unbindReq = unbindReq; expectedResp = (UnbindResp)unbindReq.getResponse(); } public void handleEvent(ServerPDUEvent event) { PDU pdu = event.getPDU(); if (pdu.equals(unbindReq)) { synchronized (this) { try { unbindResp = (UnbindResp)(session.checkResponse(pdu,expectedResp)); } catch (Exception e) { debug.write(DSESS,"exception handling unbind "+e); super.event.write(e,"exception handling unbind"); } // notify as session waits for the notification this.notify(); } } else { // all other pdus are processed by the original handler, // if any if (origListener != null) { origListener.handleEvent(event); } } } public UnbindResp getUnbindResp() { return unbindResp; } } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?