return;
}
if (response.getOptions().hasBlock1()) {
// TODO: What if request has not been sent blockwise (server error)
BlockOption block1 = response.getOptions().getBlock1();
LOGGER.finer("Response acknowledges block "+block1);
BlockwiseStatus status = exchange.getRequestBlockStatus();
if (! status.isComplete()) {
// TODO: the response code should be CONTINUE. Otherwise deliver
// Send next block
int currentSize = 1 << (4 + status.getCurrentSzx());
int nextNum = status.getCurrentNum() + currentSize / block1.getSize();
LOGGER.finer("Send next block num = "+nextNum);
status.setCurrentNum(nextNum);
status.setCurrentSzx(block1.getSzx());
Request nextBlock = getNextRequestBlock(exchange.getRequest(), status);
if (nextBlock.getToken() == null)
nextBlock.setToken(response.getToken()); // reuse same token
exchange.setCurrentRequest(nextBlock);
super.sendRequest(exchange, nextBlock);
// do not deliver response
} else if (!response.getOptions().hasBlock2()) {
// All request block have been acknowledged and we receive a piggy-backed
// response that needs no blockwise transfer. Thus, deliver it.
super.receiveResponse(exchange, response);
} else {
LOGGER.fine("Response has Block2 option and is therefore sent blockwise");
}
}
if (response.getOptions().hasBlock2()) {
BlockOption block2 = response.getOptions().getBlock2();
BlockwiseStatus status = findResponseBlockStatus(exchange, response);
if (block2.getNum() == status.getCurrentNum()) {
// We got the block we expected :-)
status.addBlock(response.getPayload());
if (response.getOptions().hasObserve())
status.setObserve(response.getOptions().getObserve());
if (block2.isM()) {
LOGGER.finer("Request the next response block");
// TODO: If this is a notification, do we have to use
// another token now?
Request request = exchange.getRequest();
int num = block2.getNum() + 1;
int szx = block2.getSzx();
boolean m = false;
Request block = new Request(request.getCode());
block.setOptions(new OptionSet(request.getOptions()));
block.setDestination(request.getDestination());
block.setDestinationPort(request.getDestinationPort());
block.setType(request.getType()); // NON could make sense over SMS or similar transports
block.getOptions().setBlock2(szx, m, num);
status.setCurrentNum(num);
// to make it easier for Observe, we do not re-use the Token
// if (!response.getOptions().hasObserve()) {
// block.setToken(request.getToken());
// }
// make sure not to use Observe for block retrieval
block.getOptions().removeObserve();
exchange.setCurrentRequest(block);
super.sendRequest(exchange, block);
} else {
LOGGER.finer("We have received all "+status.getBlockCount()+" blocks of the response. Assemble and deliver");
Response assembled = new Response(response.getCode());
assembleMessage(status, assembled, response);
assembled.setType(response.getType());
// Check if this response is a notification
int observe = status.getObserve();
if (observe != BlockwiseStatus.NO_OBSERVE) {
assembled.getOptions().setObserve(observe);
// This is necessary for notifications that are sent blockwise:
// Reset block number AND container with all blocks
exchange.setResponseBlockStatus(null);
}
LOGGER.fine("Assembled response: "+assembled);
exchange.setResponse(assembled);
super.receiveResponse(exchange, assembled);
}
} else {
// ERROR, wrong block number (server error)
// TODO: This scenario is not specified in the draft.
// Currently, we reject it and cancel the request.
LOGGER.warning("Wrong block number. Expected "+status.getCurrentNum()+" but received "+block2.getNum()+". Reject response; exchange has failed.");
if (response.getType()==Type.CON) {
EmptyMessage rst = EmptyMessage.newRST(response);
super.sendEmptyMessage(exchange, rst);
}
exchange.getRequest().cancel();