use of org.smpp.pdu.PDU in project opensmpp by OpenSmpp.
the class ReceiverBase method tryReceivePDUWithTimeout.
/**
* For specified time tries to receive a PDU from given connection by
* calling method <code>tryReceivePDU</code>.
* The method <code>tryReceivePDU</code> must be implemented in the derived
* class.
* <p>
* The timeout can be either value > 0, then it means for
* how many milliseconds will be repeatedly tried to receive a PDU.
* If the timeout is = 0 then there is only one attempt to receive a PDU.
* If the timeout is equal to Data.RECEIVE_BLOCKING, then the this method
* tries receive a PDU until it is received.
*
* @param connection the connection from which the PDU should be received
* @param expectedPDU the command id and sequence id of the received PDU
* should be equal to those of expectedPDU
* @param timeout the timeout indication
* @return the received PDU if any or null if none received
*
* @exception IOException exception during communication
* @exception PDUException incorrect format of PDU
* @exception TimeoutException rest of data not received for too long time
* @exception UnknownCommandIdException PDU with unknown id was received
* @see #tryReceivePDU(Connection,PDU)
* @see PDU#equals(Object)
*/
protected final PDU tryReceivePDUWithTimeout(Connection connection, PDU expectedPDU, long timeout) throws UnknownCommandIdException, TimeoutException, PDUException, IOException {
debug.write(DRXTX, "receivePDU: Going to receive response.");
long startTime = Data.getCurrentTime();
PDU pdu = null;
if (timeout == 0) {
// with no timeout try just once
pdu = tryReceivePDU(connection, expectedPDU);
} else {
// with timeout keep trying until get some or timeout expires
while ((pdu == null) && canContinueReceiving(startTime, timeout)) {
pdu = tryReceivePDU(connection, expectedPDU);
}
}
if (pdu != null) {
debug.write(DRXTX, "Got pdu " + pdu.debugString());
}
return pdu;
}
use of org.smpp.pdu.PDU in project opensmpp by OpenSmpp.
the class Receiver method receiveAsync.
/**
* This method receives a PDU from connection and stores it into
* <code>pduQueue</code>. It's called from the <code>ReceiverBase</code>'s
* p<code>process</code> method which is called in loop from
* <code>ProcessingThread</code>'s <code>run</code> method.
* <p>
* If an exception occurs during receiving, depending on type
* of the exception this method either just reports the exception to
* debug & event objects or stops processing to indicate
* that it isn't able to process the exception. The function
* <code>setTermException</code> is then called with the caught exception.
*
* @see ReceiverBase#run()
*/
protected void receiveAsync() {
PDU pdu = null;
try {
debug.write(DRXTXD2, "Receiver.receiveAsync() going to receive pdu.");
pdu = receivePDUFromConnection(connection, unprocessed);
// we must catch every exception as this is thread running
// on the background and we don't want the thread to be terminated
} catch (InvalidPDUException e) {
// thrown when enough data were received but further parsing
// required more than indicated by CommandLength, i.e. pdu is
// corrupted or further parsing didn't find terminating zero
// of a c-string i.e. pdu is corrupted
// must send generic nack anyway
event.write(e, "Receiver.receiveAsync(): received PDU is invalid.");
PDU expdu = e.getPDU();
int seqNr = expdu == null ? 0 : expdu.getSequenceNumber();
if (automaticNack) {
sendGenericNack(Data.ESME_RINVMSGLEN, seqNr);
} else {
pdu = new GenericNack(Data.ESME_RINVMSGLEN, seqNr);
}
} catch (UnknownCommandIdException e) {
// if received unknown pdu, we must send generic nack
event.write(e, "Receiver.receiveAsync(): Unknown command id.");
if (automaticNack) {
sendGenericNack(Data.ESME_RINVCMDID, e.getSequenceNumber());
} else {
pdu = new GenericNack(Data.ESME_RINVCMDID, e.getSequenceNumber());
}
} catch (TimeoutException e) {
// too long had unprocessed data
debug.write(DRXTX, "Receiver.receiveAsync() too long had an uncomplete message.");
} catch (PDUException e) {
// something wrong with the PDU
event.write(e, "Receiver.receiveAsync()");
PDU expdu = e.getPDU();
int seqNr = expdu == null ? 0 : expdu.getSequenceNumber();
if (automaticNack) {
sendGenericNack(e.getErrorCode(), seqNr);
} else {
pdu = new GenericNack(e.getErrorCode(), seqNr);
}
} catch (Exception e) {
// don't know what happen, let's end the show
event.write(e, "Receiver.receiveAsync()");
stopProcessing(e);
}
if (pdu != null) {
debug.write(DRXTX, "Receiver.receiveAsync(): PDU received, processing " + pdu.debugString());
if (asynchronous) {
process(pdu);
} else {
enqueue(pdu);
}
}
}
use of org.smpp.pdu.PDU in project opensmpp by OpenSmpp.
the class Receiver method setServerPDUEventListener.
/**
* Sets the event listener for asynchronous <code>Receiver</code>.
* In case there are unprocessed PDUs in the queue,
* they are removed from the queue and passed to the newly set listener.
*/
public synchronized void setServerPDUEventListener(ServerPDUEventListener pduListener) {
this.pduListener = pduListener;
this.asynchronous = pduListener != null;
if (asynchronous) {
// let's remove all pdu's from the queue as since now all
// processing should be asynchronous -- it's not wise to
// expect that the programmer will try AFTER setting the listener
// to call receive() which when in sync mode removes the pdus from
// the queue
PDU pdu;
int queueSize;
synchronized (pduQueue) {
queueSize = pduQueue.size();
for (int i = 0; i < queueSize; i++) {
pdu = (PDU) pduQueue.dequeue();
process(pdu);
}
}
}
}
use of org.smpp.pdu.PDU in project opensmpp by OpenSmpp.
the class Receiver method tryReceivePDU.
/**
* This method tries to receive one PDU from the connection.
* It is called in cycle from <code>tryReceivePDUWithTimeout</code> until
* timeout expires. <code>tryReceivePDUWithTimeout</code> is called
* either from <code>receiveAsync</code> as asynchronous receive on
* background or from <code>receive</code> as synchronous receive.
* It either gets pdu from the queue or tries to receive it from connection
* using <code>receivePDUFromConnection</code> depending on
* the value of the <code>receiver</code> flag. The method
* checks if the actualy received PUD is equal to <code>expectedPDU</code>.
*
* @exception IOException exception during communication
* @exception PDUException incorrect format of PDU
* @exception TimeoutException rest of PDU not received for too long time
* @exception UnknownCommandIdException PDU with unknown id was received
* @see ReceiverBase#tryReceivePDUWithTimeout(Connection,PDU,long)
* @see #receiveAsync()
* @see ReceiverBase#run()
*/
protected PDU tryReceivePDU(Connection connection, PDU expectedPDU) throws UnknownCommandIdException, TimeoutException, PDUException, IOException {
PDU pdu = null;
if (receiver) {
debug.write(DRXTXD2, "Is receiver/transciever => trying to get from queue.");
synchronized (pduQueue) {
if (expectedPDU == null) {
// i.e. any pdu is acceptable
if (!pduQueue.isEmpty()) {
pdu = (PDU) pduQueue.dequeue();
}
} else {
pdu = (PDU) pduQueue.dequeue(expectedPDU);
}
if (pdu == null) {
try {
pduQueue.wait(getQueueWaitTimeout());
} catch (InterruptedException e) {
// we don't care
debug.write(DRXTX, "tryReceivePDU got interrupt waiting for queue");
}
}
}
} else {
debug.write(DRXTX, "Is transmitter only => trying to receive from connection.");
pdu = receivePDUFromConnection(connection, unprocessed);
if (pdu != null) {
if ((expectedPDU == null) || !pdu.equals(expectedPDU)) {
debug.write(DRXTX, "This is not the pdu we expect, processing" + pdu.debugString());
enqueue(pdu);
pdu = null;
}
}
}
return pdu;
}
use of org.smpp.pdu.PDU in project opensmpp by OpenSmpp.
the class ReceiverBase method tryGetUnprocessedPDU.
/**
* 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();
// Reset counter after successful createPDU (as per bug #2138444):
messageIncompleteRetryCount = 0;
} 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.");
// as it's incomplete - wait for new data
unprocessed.setHasUnprocessed(false);
unprocessed.setExpected(Data.PDU_HEADER_SIZE);
} catch (MessageIncompleteException e) {
// busy servers and PDUs split across TCP packets.
if (messageIncompleteRetryCount > 5) {
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.");
// as it's incomplete - wait for new data
unprocessed.setHasUnprocessed(false);
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();
// caller will decide what to do
throw e;
}
// 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;
}
Aggregations