receiverbase.java
来自「Logica lastest SMPP API」· Java 代码 · 共 408 行 · 第 1/2 页
JAVA
408 行
* PDU from them and buffering data in case the PDU * isn't still complete. It has timeout checking for incomplete * messages: if the message isn't received completly for certain time * and no new data are received for this time, then exception is thrown * as this could indicate communication problem. * * @param connection the connection to receive the data from * @return either PDU, if complete received or null * * @exception IOException exception during communication * @exception PDUException incorrect format of PDU * @throws TimeoutException rest of data not received for too long time * @throws UnknownCommandIdException PDU with unknown id was received * @see Connection * @see Unprocessed */ final protected PDU receivePDUFromConnection(Connection connection, Unprocessed unprocessed) throws UnknownCommandIdException, TimeoutException, PDUException, IOException { debug.write(DRXTXD2,"ReceiverBase.receivePDUFromConnection start"); PDU pdu = null; ByteBuffer buffer; ByteBuffer unprocBuffer; try { // first check if there is something left from the last time if (unprocessed.getHasUnprocessed()) { unprocBuffer = unprocessed.getUnprocessed(); debug.write(DRXTX,"have unprocessed "+unprocBuffer.length()+" bytes from previous try"); pdu = tryGetUnprocessedPDU(unprocessed); } if (pdu == null) { // only if we didn't manage to get pdu from unproc buffer = connection.receive(); unprocBuffer = unprocessed.getUnprocessed(); // if received something now or have something from the last receive if (buffer.length() != 0) { unprocBuffer.appendBuffer(buffer); unprocessed.setLastTimeReceived(); pdu = tryGetUnprocessedPDU(unprocessed); } else { debug.write(DRXTXD2,"no data received this time."); // check if it's not too long since we received any data long timeout = getReceiveTimeout(); if ((unprocBuffer.length() > 0) && ((unprocessed.getLastTimeReceived() + timeout) < Data.getCurrentTime())) { debug.write(DRXTX,"and it's been very long time."); unprocessed.reset(); throw new TimeoutException(timeout, unprocessed.getExpected(), unprocBuffer.length()); } } } } catch (UnknownCommandIdException e) { // paolo@bulksms.com: if we got an UnknownCommandIdException here, the // chances are excellent that // some trailing garbage is hanging arounf in the unprocessed buffer. // given that it's unlikely that it contained a valid PDU, we don't // rethrow the error - nothing to respond to with a gnack. // Was originally just checking this if the unprocessed buffer had // content, but that's not enough. debug.write(DRXTX,"There is _probably_ garbage in the unprocessed buffer - flushing unprocessed buffer now."); event.write(e,"There is _probably_ garbage in the unprocessed buffer - flushing unprocessed buffer now."); unprocessed.reset(); } debug.write(DRXTXD2,"ReceiverBase.receivePDUFromConnection finished"); return pdu; } /** * Tries to create a PDU from the buffer provided. * Returns the PDU if successfull or null if not or an exception * if the PDU is incorrect. */ private final PDU tryGetUnprocessedPDU(Unprocessed unprocessed) throws UnknownCommandIdException, PDUException { debug.write(DRXTX,"trying to create pdu from unprocessed buffer"); PDU pdu = null; ByteBuffer unprocBuffer = unprocessed.getUnprocessed(); try { pdu = PDU.createPDU(unprocBuffer); //System.out.println("SEQ No In Receiver base: "+pdu.getSequenceNumber()); unprocessed.check(); } catch (HeaderIncompleteException e) { // the header wasn't received completly, we will try to // receive the rest next time debug.write(DRXTXD,"incomplete message header, will wait for the rest."); unprocessed.setHasUnprocessed(false); // as it's incomplete - wait for new data unprocessed.setExpected(Data.PDU_HEADER_SIZE); } catch (MessageIncompleteException e) { if (messageIncompleteRetryCount > 1) { // paolo@bulksms.com messageIncompleteRetryCount = 0; debug.write(DRXTXD,"Giving up on incomplete messages - probably garbage in unprocessed buffer. Flushing unprocessed buffer."); event.write("Giving up on incomplete messages - probably garbage in unprocessed buffer. Flushing unprocessed buffer."); unprocessed.reset(); } // the message wasn't received completly, less bytes than command // length has been received, will try to receive the rest next time debug.write(DRXTXD,"incomplete message, will wait for the rest."); unprocessed.setHasUnprocessed(false); // as it's incomplete - wait for new data unprocessed.setExpected(Data.PDU_HEADER_SIZE); messageIncompleteRetryCount++; } catch (UnknownCommandIdException e) { // message with invalid id was received, should send generic_nack debug.write(DRXTX,"unknown pdu, might remove from unprocessed buffer. CommandId=" + e.getCommandId()); if (e.getCommandLength() <= unprocBuffer.length()) { // have already enough to remove try { unprocBuffer.removeBytes(e.getCommandLength()); } catch (NotEnoughDataInByteBufferException e1) { // can't happen, we've checked it above throw new Error("Not enough data in buffer even if previously checked that there was enough."); } unprocessed.check(); throw e; // caller will decide what to do } // paolo@bulksms.com: added this: see why in caller. Advantage: lets // us trap garbage PDUs that break things by being trapped in the // unprocessed buffer eternally. Disadvantage: if this was a valid // (well-formed) PDU with an unknown command id AND it was not fully // read into the buffer in one go, then: // 1) we will respond to the part _was_ already read (which we know // contains at least a header - see code in PDU) with an error, which // is fine. // 2) when we receive the second part of the incomplete PDU, it will // effectively seem to us to be an invalid PDU itself. It could be // processed as follows: // - as an unknown command_id again, which is fine; or // - as an incomplete message, which is a problem, because it will // then have the subsequent PDU tacked to the end of it, and // that PDU will then be discarded as well (and almost certainly // discarded via an UnknownCommandIdException again). throw e; } // paolo@bulksms.com: safer to catch all other PDU exceptions and force // force a check() here - some exception in parsing should not be allowed // to leave ghost data in the Unprocessed buffer (even though this is now // less likely after improvements to PDU.createPDU()): catch (PDUException e) { unprocessed.check(); throw e; } if (pdu != null) { debug.write(DRXTX,"received complete pdu"+pdu.debugString()); debug.write(DRXTX,"there is "+unprocBuffer.length()+ " bytes left in unprocessed buffer"); } // unprocessed.check(); return pdu; } /** * Sets the timeout for receiving the complete message. * If no data are received for time longer then this timeout and there * is still not completly received PDU in the internal buffer, * <code>TimeoutException</code> is thrown. * * @param timeout the new timeout value * * @see #receivePDUFromConnection(Connection,Unprocessed) * @see TimeoutException */ public void setReceiveTimeout(long timeout) { receiveTimeout = timeout; } /** * Returns the current setting of the receiving timeout. * * @return the current timeout value */ public long getReceiveTimeout() { return receiveTimeout; } /** * Depending on value of <code>timeout</code> and on <code>startTime</code> * returns if it's still possible to continue in receiving of message. * <code>timeout</code> can indicate either timeout in milliseconds * (if > 0), or that there has to be only one attempt to receive * a message (if = 0) or that the the receiving shuld continue until * a PDU is received (if = Data.RECEIVE_BLOCKING). * * @param startTime when the receiving started * @param timeout timeout indication * @return if it's possible to continue receiving */ private boolean canContinueReceiving(long startTime, long timeout) { return timeout == Data.RECEIVE_BLOCKING ? true : Data.getCurrentTime() <= (startTime + timeout); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?