/** Close the session */ public void close() { if (sLogger.isActivated()) { sLogger.debug("Close session"); } // Cancel transfer mCancelTransfer = true; // Close the connection if (connection != null) { connection.close(); } // Unblock request transaction if (mRequestTransaction != null) { mRequestTransaction.terminate(); } // Unblock report transaction if (mReportTransaction != null) { mReportTransaction.terminate(); } // Unblock MSRP transaction if (mMsrpTransaction != null) { mMsrpTransaction.terminate(); } }
/** * 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 }
// Changed by Deutsche Telekom private void sendMsrpSendRequest( String txId, String to, String from, String msrpMsgId, String contentType, int dataSize, byte data[], long firstByte, long lastByte, long totalSize) throws NetworkException { ByteArrayOutputStream buffer = null; try { boolean isLastChunk = (lastByte == totalSize); // Create request buffer = new ByteArrayOutputStream(4000); buffer.reset(); buffer.write(MsrpConstants.MSRP_HEADER.getBytes(UTF8)); buffer.write(MsrpConstants.CHAR_SP); buffer.write(txId.getBytes(UTF8)); buffer.write((" " + MsrpConstants.METHOD_SEND).getBytes(UTF8)); buffer.write(NEW_LINE); String toHeader = MsrpConstants.HEADER_TO_PATH + ": " + to + MsrpConstants.NEW_LINE; buffer.write(toHeader.getBytes(UTF8)); String fromHeader = MsrpConstants.HEADER_FROM_PATH + ": " + from + MsrpConstants.NEW_LINE; buffer.write(fromHeader.getBytes(UTF8)); // Changed by Deutsche Telekom String msgIdHeader = MsrpConstants.HEADER_MESSAGE_ID + ": " + msrpMsgId + MsrpConstants.NEW_LINE; buffer.write(msgIdHeader.getBytes(UTF8)); // Write byte range String byteRange = MsrpConstants.HEADER_BYTE_RANGE + ": " + firstByte + "-" + lastByte + "/" + totalSize + MsrpConstants.NEW_LINE; buffer.write(byteRange.getBytes(UTF8)); // Write optional headers // Changed by Deutsche Telekom // According with GSMA guidelines if (mFailureReportOption) { String header = MsrpConstants.HEADER_FAILURE_REPORT + ": yes" + MsrpConstants.NEW_LINE; buffer.write(header.getBytes(UTF8)); } if (mSuccessReportOption) { String header = MsrpConstants.HEADER_SUCCESS_REPORT + ": yes" + MsrpConstants.NEW_LINE; buffer.write(header.getBytes(UTF8)); } // Write content type if (contentType != null) { String content = MsrpConstants.HEADER_CONTENT_TYPE + ": " + contentType + MsrpConstants.NEW_LINE; buffer.write(content.getBytes(UTF8)); } // Write data if (data != null) { buffer.write(NEW_LINE); buffer.write(data, 0, dataSize); buffer.write(NEW_LINE); } // Write end of request buffer.write(MsrpConstants.END_MSRP_MSG.getBytes(UTF8)); buffer.write(txId.getBytes(UTF8)); if (isLastChunk) { // '$' -> last chunk buffer.write(MsrpConstants.FLAG_LAST_CHUNK); } else { // '+' -> more chunk buffer.write(MsrpConstants.FLAG_MORE_CHUNK); } buffer.write(NEW_LINE); // Send chunk if (mFailureReportOption) { if (mMsrpTransaction != null) { mMsrpTransaction.handleRequest(); mRequestTransaction = null; } else { mRequestTransaction = new RequestTransaction(mRcsSettings); } connection.sendChunk(buffer.toByteArray()); buffer.close(); if (mRequestTransaction != null) { mRequestTransaction.waitResponse(); if (!mRequestTransaction.isResponseReceived()) { throw new NetworkException("Failed to receive transaction response!"); } } } else { connection.sendChunk(buffer.toByteArray()); buffer.close(); if (mMsrpTransaction != null) { mMsrpTransaction.handleRequest(); } } } catch (IOException e) { throw new NetworkException("Failed to read chunk data!", e); } finally { CloseableUtils.tryToClose(buffer); } }
/** * 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); } }