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 + -
显示快捷键?