Example #1
0
  /**
   * Receive MSRP response
   *
   * @param code Response code
   * @param txId Transaction ID
   * @param headers MSRP headers
   */
  public void receiveMsrpResponse(int code, String txId, Hashtable<String, String> headers) {
    // Consider media is established when we received something
    mIsEstablished = true;

    if (sLogger.isActivated()) {
      sLogger.info("Response received (code=" + code + ", transaction=" + txId + ")");
    }

    if (mFailureReportOption) {
      // Notify progress
      if (!mCancelTransfer && mProgress.size() > 0) {
        mMsrpEventListener.msrpTransferProgress(mProgress.elementAt(0), mTotalSize);
        mProgress.removeElementAt(0);
      }
    }

    // Notify request transaction
    if (mRequestTransaction != null) {
      mRequestTransaction.notifyResponse(code, headers);
    }

    // Notify MSRP transaction
    if (mMsrpTransaction != null) {
      mMsrpTransaction.handleResponse();
    }

    // Notify event listener
    if (code != 200) {
      // Changed by Deutsche Telekom
      String cpimMsgId = null;
      TypeMsrpChunk typeMsrpChunk = TypeMsrpChunk.Unknown;
      MsrpTransactionInfo msrpTransactionInfo = getMsrpTransactionInfo(txId);
      if (msrpTransactionInfo != null) {
        cpimMsgId = msrpTransactionInfo.mCpimMsgId;
        typeMsrpChunk = msrpTransactionInfo.mTypeMsrpChunk;
      }
      mMsrpEventListener.msrpTransferError(cpimMsgId, "error response " + code, typeMsrpChunk);

      // Changed by Deutsche Telekom
      // If an error is received it couldn't get any better nor worse; transaction has reached
      // final state
      removeMsrpTransactionInfo(txId);
    }

    // Don't remove transaction info in general from list as this could be a preliminary answer
  }
Example #2
0
  /**
   * Receive MSRP REPORT request
   *
   * @param txId Transaction ID
   * @param headers MSRP headers
   * @throws NetworkException
   * @throws FileAccessException
   */
  public void receiveMsrpReport(String txId, Hashtable<String, String> headers)
      throws FileAccessException, NetworkException {
    // Changed by Deutsche Telekom
    // Example of an MSRP REPORT request:
    // MSRP b276bb5b0adb22f6 SEND
    // To-Path: msrp://10.108.25.89:19494/n02s00i2t0+519;tcp
    // From-Path: msrp://10.102.192.68:20000/1375944013409;tcp
    // Message-ID: MID-3BCqcBUXKA
    // Byte-Range: 1-305/305
    // Content-Type: message/cpim
    //
    // From: <sip:[email protected]>
    // To: <sip:[email protected]>
    // NS: imdn <urn:ietf:params:imdn>
    // imdn.Message-ID: Msg2BCqcBUWKA
    // DateTime: 2013-08-08T06:40:56.000Z
    // imdn.Disposition-Notification: positive-delivery, display
    //
    // Content-type: text/plain; charset=utf-8
    // Content-length: 1
    //
    // F
    // -------b276bb5b0adb22f6$
    //
    // MSRP b276bb5b0adb22f6 200 OK
    // To-Path: msrp://10.102.192.68:20000/1375944013409;tcp
    // From-Path: msrp://10.108.25.89:19494/n02s00i2t0+519;tcp
    // -------b276bb5b0adb22f6$
    //
    // MSRP n02s00i2t0+1937 REPORT
    // To-Path: msrp://10.102.192.68:20000/1375944013409;tcp
    // From-Path: msrp://10.108.25.89:19494/n02s00i2t0+519;tcp
    // Status: 000 413 413
    // Message-ID: MID-3BCqcBUXKA
    // Byte-Range: 1-305/305
    // -------n02s00i2t0+1937$

    if (sLogger.isActivated()) {
      sLogger.info("REPORT request received (transaction=" + txId + ")");
    }

    // Changed by Deutsche Telekom
    String msrpMsgId = headers.get(MsrpConstants.HEADER_MESSAGE_ID);
    String cpimMsgId = null;

    String originalTransactionId = null;
    TypeMsrpChunk typeMsrpChunk = TypeMsrpChunk.Unknown;
    MsrpTransactionInfo msrpTransactionInfo = getMsrpTransactionInfoByMessageId(msrpMsgId);
    if (msrpTransactionInfo != null) {
      typeMsrpChunk = msrpTransactionInfo.mTypeMsrpChunk;
      originalTransactionId = msrpTransactionInfo.mTransactionId;
      cpimMsgId = msrpTransactionInfo.mCpimMsgId;
      if (sLogger.isActivated()) {
        sLogger.debug(
            "REPORT request details; originalTransactionId="
                + originalTransactionId
                + "; cpimMsgId="
                + cpimMsgId
                + "; typeMsrpChunk="
                + typeMsrpChunk);
      }
    }

    // Changed by Deutsche Telekom
    // Test if a failure report is needed
    boolean failureReportNeeded = true;
    String failureHeader = headers.get(MsrpConstants.HEADER_FAILURE_REPORT);
    if ((failureHeader != null) && failureHeader.equalsIgnoreCase("no")) {
      failureReportNeeded = false;
    }

    // Send MSRP response if requested
    if (failureReportNeeded) {
      sendMsrpResponse(MsrpConstants.STATUS_200_OK, txId, headers);
    }

    // Check status code
    int statusCode = ReportTransaction.parseStatusCode(headers);
    if (statusCode != 200) {
      // Changed by Deutsche Telekom
      mMsrpEventListener.msrpTransferError(cpimMsgId, "error report " + statusCode, typeMsrpChunk);
    }

    // Notify report transaction
    if (mReportTransaction != null) {
      mReportTransaction.notifyReport(statusCode, headers);
    }

    // Changed by Deutsche Telekom
    // Remove transaction info from list as transaction has reached a final state
    removeMsrpTransactionInfo(originalTransactionId);
  }
Example #3
0
  /**
   * Receive MSRP SEND request
   *
   * @param txId Transaction ID
   * @param headers Request headers
   * @param flag Continuation flag
   * @param data Received data
   * @param totalSize Total size of the content
   * @throws NetworkException
   * @throws PayloadException
   * @throws ContactManagerException
   */
  public void receiveMsrpSend(
      String txId, Hashtable<String, String> headers, int flag, byte[] data, long totalSize)
      throws PayloadException, NetworkException, ContactManagerException {
    mIsEstablished = true;
    if (sLogger.isActivated()) {
      sLogger.debug(
          new StringBuilder("SEND request received (flag=")
              .append(flag)
              .append(", transaction=")
              .append(txId)
              .append(", totalSize=")
              .append(totalSize)
              .append(")")
              .toString());
    }

    String msgId = headers.get(MsrpConstants.HEADER_MESSAGE_ID);
    boolean failureReportNeeded = true;
    String failureHeader = headers.get(MsrpConstants.HEADER_FAILURE_REPORT);
    if ((failureHeader != null) && failureHeader.equalsIgnoreCase("no")) {
      failureReportNeeded = false;
    }
    if (failureReportNeeded) {
      sendMsrpResponse(MsrpConstants.STATUS_200_OK, txId, headers);
    }
    if (data == null) {
      if (sLogger.isActivated()) {
        sLogger.debug("Empty chunk");
      }
      return;
    }
    mReceivedChunks.addChunk(data);

    if (flag == MsrpConstants.FLAG_LAST_CHUNK) {
      if (sLogger.isActivated()) {
        sLogger.info("Transfer terminated");
      }
      byte[] dataContent = mReceivedChunks.getReceivedData();
      mReceivedChunks.resetCache();

      String contentTypeHeader = headers.get(MsrpConstants.HEADER_CONTENT_TYPE);
      mMsrpEventListener.receiveMsrpData(msgId, dataContent, contentTypeHeader);

      boolean successReportNeeded = false;
      String reportHeader = headers.get(MsrpConstants.HEADER_SUCCESS_REPORT);
      if ((reportHeader != null) && reportHeader.equalsIgnoreCase("yes")) {
        successReportNeeded = true;
      }
      if (successReportNeeded) {
        sendMsrpReportRequest(txId, headers, dataContent.length, totalSize);
      }
    } else if (flag == MsrpConstants.FLAG_ABORT_CHUNK) {
      if (sLogger.isActivated()) {
        sLogger.info("Transfer aborted");
      }
      mMsrpEventListener.msrpTransferAborted();
    } else if (flag == MsrpConstants.FLAG_MORE_CHUNK) {
      if (sLogger.isActivated()) {
        sLogger.debug("Transfer in progress...");
      }
      byte[] dataContent = mReceivedChunks.getReceivedData();
      boolean resetCache =
          mMsrpEventListener.msrpTransferProgress(
              mReceivedChunks.getCurrentSize(), totalSize, dataContent);

      /*
       * Data are only consumed chunk by chunk in file transfer & image share. In a chat
       * session only the whole message is consumed after receiving the last chunk.
       */
      if (resetCache) {
        mReceivedChunks.resetCache();
      }
    }
  }
Example #4
0
  /**
   * Send chunks
   *
   * @param inputStream Input stream
   * @param msgId Message ID
   * @param contentType Content type to be sent
   * @param totalSize Total size of content
   * @param typeMsrpChunk Type of MSRP chunk
   * @throws NetworkException
   */
  public void sendChunks(
      InputStream inputStream,
      String msgId,
      String contentType,
      final long totalSize,
      TypeMsrpChunk typeMsrpChunk)
      throws NetworkException {
    if (sLogger.isActivated()) {
      sLogger.info("Send content (" + contentType + " - MSRP chunk type: " + typeMsrpChunk + ")");
    }
    this.mTotalSize = totalSize;
    try {
      byte data[] = new byte[MsrpConstants.CHUNK_MAX_SIZE];
      long firstByte = 1;
      long lastByte = 0;
      mCancelTransfer = false;
      if (mSuccessReportOption) {
        mReportTransaction = new ReportTransaction();
      } else {
        mReportTransaction = null;
      }
      if (mFailureReportOption) {
        mMsrpTransaction = new MsrpTransaction();
      } else {
        mMsrpTransaction = null;
      }

      // Changed by Deutsche Telekom
      // Calculate number of needed chunks
      final int totalChunks = (int) Math.ceil(totalSize / (double) MsrpConstants.CHUNK_MAX_SIZE);

      new Thread(
              new Runnable() {

                @Override
                public void run() {
                  if (mMsrpTransaction != null) {
                    while ((totalChunks - mMsrpTransaction.getNumberReceivedOk()) > 0
                        && !mCancelTransfer) {
                      mMsrpEventListener.msrpTransferProgress(
                          mMsrpTransaction.getNumberReceivedOk() * MsrpConstants.CHUNK_MAX_SIZE,
                          totalSize);
                      try {
                        Thread.sleep(500);
                      } catch (InterruptedException e) {
                        /* Nothing to be done here */
                      }
                    }
                  }
                }
              })
          .start();

      // Changed by Deutsche Telekom
      String newTransactionId = null;

      // Changed by Deutsche Telekom
      // RFC4975, section 7.1.1. Sending SEND Requests
      // When an endpoint has a message to deliver, it first generates a new
      // Message-ID. The value MUST be highly unlikely to be repeated by
      // another endpoint instance, or by the same instance in the future.
      // Message-ID value follows the definition in RFC4975, section 9
      String msrpMsgId = IdGenerator.generateMessageID();

      // Send data chunk by chunk
      for (int i = inputStream.read(data);
          (!mCancelTransfer) & (i > -1);
          i = inputStream.read(data)) {
        // Update upper byte range
        lastByte += i;

        // Changed by Deutsche Telekom
        newTransactionId = generateTransactionId();
        addMsrpTransactionInfo(newTransactionId, msrpMsgId, msgId, typeMsrpChunk);

        // Send a chunk
        // Changed by Deutsche Telekom
        sendMsrpSendRequest(
            newTransactionId,
            mTo,
            mFrom,
            msrpMsgId,
            contentType,
            i,
            data,
            firstByte,
            lastByte,
            totalSize);

        // Update lower byte range
        firstByte += i;

        // Progress management
        if (mFailureReportOption) {
          // Add value in progress vector
          mProgress.add(lastByte);
        } else {
          // Direct notification
          if (!mCancelTransfer) {
            mMsrpEventListener.msrpTransferProgress(lastByte, totalSize);
          }
        }
      }

      if (mCancelTransfer) {
        // Transfer has been aborted
        return;
      }

      // Waiting msrpTransaction
      if (mMsrpTransaction != null) {
        // Wait until all data have been reported
        mMsrpTransaction.waitAllResponses();

        // Notify event listener
        if (mMsrpTransaction.isAllResponsesReceived()) {
          mMsrpEventListener.msrpDataTransfered(msgId);
        } else {
          if (!mMsrpTransaction.isTerminated()) {
            // Changed by Deutsche Telekom
            mMsrpEventListener.msrpTransferError(msgId, "response timeout 408", typeMsrpChunk);
          }
        }
      }

      // Waiting reportTransaction
      if (mReportTransaction != null) {
        // Wait until all data have been reported
        while (!mReportTransaction.isTransactionFinished(totalSize)) {
          mReportTransaction.waitReport();
          if (mReportTransaction.getStatusCode() != 200) {
            // Error
            break;
          }
        }

        // Notify event listener
        if (mReportTransaction.getStatusCode() == 200) {
          mMsrpEventListener.msrpDataTransfered(msgId);
        } else {
          // Changed by Deutsche Telekom
          mMsrpEventListener.msrpTransferError(
              msgId, "error report " + mReportTransaction.getStatusCode(), typeMsrpChunk);
        }
      }

      // No transaction
      if (mMsrpTransaction == null && mReportTransaction == null) {
        // Notify event listener
        mMsrpEventListener.msrpDataTransfered(msgId);
      }
    } catch (IOException e) {
      throw new NetworkException(
          new StringBuilder("Send chunk failed for msgId : ").append(msgId).toString(), e);

    } finally {
      CloseableUtils.tryToClose(inputStream);
    }
  }