⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 receiverbase.java

📁 Short Message Peer to Peer
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
					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 around 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.
			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);
			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;
				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;
		} catch (PDUException 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()):
			unprocessed.check();
			throw e;
		}
		/* paolo@bulksms.com: concerned that this is too broad, and will
		   stop useful exceptions from being passed back up the call stack,
			so disabling for now:
		} catch (Exception e) {
			debug.write(DRXTX, "Exception catched: " + e.toString());
			StringWriter stringWriter = new StringWriter();
			PrintWriter printWriter = new PrintWriter(stringWriter);
			e.printStackTrace(printWriter);
			debug.write(DRXTX, stringWriter.toString());
		}
		*/
		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);
	}

}
/*
 * $Log: ReceiverBase.java,v $
 * Revision 1.4  2006/03/09 16:24:14  sverkera
 * Removed compiler and javadoc warnings
 *
 * Revision 1.3  2004/09/04 09:34:50  paoloc
 * no message
 *
 * Revision 1.2  2004/09/04 09:00:27  paoloc
 * Various changes which deal better with invalid ((non-spec or garbage) data being received. Previously, such data could get a Receiver object stuck in a state in which it stops passing incoming data to the application.
 *
 * Revision 1.1  2003/07/23 00:28:39  sverkera
 * Imported
 *
 * 
 * Old changelog:
 * 13-07-01 ticp@logica.com start(), stop(), setReceiveTimeout(),
 * 						    getReceiveTimeout(), setTermException(),
 *						    getTermException() made not synchronized;
 *						    receive(long) & receive(PDU) made synchronized
 *						    so the receiver no longer locks up
 * 13-07-01 ticp@logica.com the call to receiveAsync() in run() now enclosed
 *						    in try-finally and the status RCV_FINISHED
 *						    is set in finally block so the finished status
 *						    is now reported correctly even in case of exception
 * 13-07-01 ticp@logica.com some debug lines corrected; some added
 * 08-08-01 ticp@logica.com added support for Session's asynchronous processing capability
 * 23-08-01 ticp@logica.com added async capability exhibited that if more than
 *						    one pdu is read from connection at once (in one
 *						    connection.receive(), the additional ones aren't
 *						    processed. this behaviour was corrected.
 * 23-08-01 ticp@logica.com added yield() to run() to give chance to other
 *						    threads
 * 26-09-01 ticp@logica.com debug code categorized to groups
 * 01-10-01 ticp@logica.com now derived from new ProcessingThread which implements
 *						    the thread related issues; this change allows to focus
 *						    only on the receiving related in the ReceiverBase
 *						    and on the thread management in the ProcessingThread;
 *						    function covered by ProcessingThread removed
 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -