private void updateTimer() {

    cancelTimer();

    timeoutTimer =
        parent
            .getMsrpResources()
            .getThreadFarm()
            .schedule(
                new Runnable() {
                  public void run() {
                    if (Logger.isLoggable(Logger.Level.DEBUG, TAG)) {
                      Logger.d(
                          TAG, "timeout timer fired for " + receivedMessageMetaData.getMsgID());
                    }
                    synchronized (MessageReassembler.this) {
                      store.receivingFinished(true);

                      // notify the app
                      parent
                          .getApplication()
                          .messageRecevied(
                              receivedMessageMetaData.getMsgID(), receivedMessageMetaData, store);
                    }
                  }
                },
                TIMEOUT_IN_SECONDS,
                TimeUnit.SECONDS);
  }
  public final synchronized MsrpResponse.ResponseCode handleNextRequest(MsrpSendRequest request) {
    if (Logger.isLoggable(Logger.Level.DEBUG, TAG)) {
      Logger.d(
          TAG,
          "enter (txID=" + request.getTransactionID() + ", msgID=" + request.getMessageID() + ")");
    }

    MsrpResponse.ResponseCode returnCode = MsrpResponse.RESPONSE_200_OK;

    long start;
    if (request.getChunkType() == MsrpSendRequest.ChunkType.head
        || request.getChunkType() == MsrpSendRequest.ChunkType.complete)
      start = request.getByteRange().getStart() - skipBytes - 1;
    else
      start =
          -1; // this is a subsequent chunk piece for an ongoing chunk, we don't need to seek() in
              // the msgStore

    // store the recevied content
    byteCounter +=
        store.store(
            start,
            request.getBody(),
            request.getBodyStartPosition(),
            request.getBody().length - request.getBodyStartPosition());

    /*
     * A sub-sequent chunk will contains the byte-range start position relative to the msrp-body.
     * Since this msrp-body contains a cpim header which we don't want to have,
     * we need to keep track of this such.
     */
    skipBytes += request.getBodyStartPosition();

    final Continuation continuation = request.getContinuation();

    /*
     * We expect more chunks (or chunk pieces) to arraive
     */
    if (continuation == null || continuation == Continuation.more) {
      // notify the app
      parent
          .getApplication()
          .moreBytesRecevied(
              request.getMessageID(),
              byteCounter,
              receivedMessageMetaData.getExpectedMsgSize(),
              store);

      // update timer
      updateTimer();

      if (wasAborted) {
        returnCode = MsrpResponse.RESPONSE_413;
      }
    }

    /*
     * Receiving was finished
     */
    else {
      // cancel
      cancelTimer();

      // release resources
      store.receivingFinished(continuation != Continuation.done);

      // notify the app
      parent
          .getApplication()
          .messageRecevied(request.getMessageID(), receivedMessageMetaData, store);

      parent.getMessageReceiver().remove(receivedMessageMetaData.getMsgID());
    }

    return returnCode;
  }