All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.android.telephony.ims.SipMessage Maven / Gradle / Ivy

Go to download

A library jar that provides APIs for Applications written for the Google Android Platform.

There is a newer version: 15-robolectric-12650502
Show newest version
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.telephony.ims;

import static java.nio.charset.StandardCharsets.UTF_8;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;

import com.android.internal.telephony.SipMessageParsingUtils;

import java.util.Arrays;
import java.util.Objects;

/**
 * Represents a partially encoded SIP message. See RFC 3261 for more information on how SIP
 * messages are structured and used.
 * 

* The SIP message is represented in a partially encoded form in order to allow for easier * verification and should not be used as a generic SIP message container. * @hide */ @SystemApi public final class SipMessage implements Parcelable { // Should not be set to true for production! private static final boolean IS_DEBUGGING = Build.IS_ENG; private static final String CRLF = "\r\n"; private final String mStartLine; private final String mHeaderSection; private final byte[] mContent; private final String mViaBranchParam; private final String mCallIdParam; /** * Represents a partially encoded SIP message. * * @param startLine The start line of the message, containing either the request-line or * status-line. * @param headerSection A String containing the full unencoded SIP message header. * @param content SIP message body. */ public SipMessage(@NonNull String startLine, @NonNull String headerSection, @NonNull byte[] content) { Objects.requireNonNull(startLine, "Required parameter is null: startLine"); Objects.requireNonNull(headerSection, "Required parameter is null: headerSection"); Objects.requireNonNull(content, "Required parameter is null: content"); mStartLine = startLine; mHeaderSection = headerSection; mContent = content; mViaBranchParam = SipMessageParsingUtils.getTransactionId(mHeaderSection); if (TextUtils.isEmpty(mViaBranchParam)) { throw new IllegalArgumentException("header section MUST contain a branch parameter " + "inside of the Via header."); } mCallIdParam = SipMessageParsingUtils.getCallId(mHeaderSection); } /** * Private constructor used only for unparcelling. */ private SipMessage(Parcel source) { mStartLine = source.readString(); mHeaderSection = source.readString(); mContent = new byte[source.readInt()]; source.readByteArray(mContent); mViaBranchParam = source.readString(); mCallIdParam = source.readString(); } /** * @return The start line of the SIP message, which contains either the request-line or * status-line. */ public @NonNull String getStartLine() { return mStartLine; } /** * @return The full, unencoded header section of the SIP message. */ public @NonNull String getHeaderSection() { return mHeaderSection; } /** * @return the SIP message body. */ public @NonNull byte[] getContent() { return mContent; } /** * @return the branch parameter enclosed in the Via header key's value. See RFC 3261 section * 20.42 for more information on the Via header. */ public @NonNull String getViaBranchParameter() { return mViaBranchParam; } /** * @return the value associated with the call-id header of this SIP message. See RFC 3261 * section 20.8 for more information on the call-id header. If {@code null}, then there was no * call-id header found in this SIP message's headers. */ public @Nullable String getCallIdParameter() { return mCallIdParam; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString(mStartLine); dest.writeString(mHeaderSection); dest.writeInt(mContent.length); dest.writeByteArray(mContent); dest.writeString(mViaBranchParam); dest.writeString(mCallIdParam); } public static final @NonNull Creator CREATOR = new Creator() { @Override public SipMessage createFromParcel(Parcel source) { return new SipMessage(source); } @Override public SipMessage[] newArray(int size) { return new SipMessage[size]; } }; @Override public String toString() { StringBuilder b = new StringBuilder(); b.append("StartLine: ["); if (IS_DEBUGGING) { b.append(mStartLine); } else { b.append(sanitizeStartLineRequest(mStartLine)); } b.append("], Header: ["); if (IS_DEBUGGING) { b.append(mHeaderSection); } else { // only identify transaction id/call ID when it is available. b.append("***"); } b.append("], Content: "); b.append(getContent().length == 0 ? "[NONE]" : "[NOT SHOWN]"); return b.toString(); } /** * Detect if this is a REQUEST and redact Request-URI portion here, as it contains PII. */ private String sanitizeStartLineRequest(String startLine) { if (!SipMessageParsingUtils.isSipRequest(startLine)) return startLine; String[] splitLine = startLine.split(" "); return splitLine[0] + " " + splitLine[2]; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; SipMessage that = (SipMessage) o; return mStartLine.equals(that.mStartLine) && mHeaderSection.equals(that.mHeaderSection) && Arrays.equals(mContent, that.mContent); } @Override public int hashCode() { int result = Objects.hash(mStartLine, mHeaderSection); result = 31 * result + Arrays.hashCode(mContent); return result; } /** * According RFC-3261 section 7, SIP is a text protocol and uses the UTF-8 charset. Its format * consists of a start-line, one or more header fields, an empty line indicating the end of the * header fields, and an optional message-body. * *

* Returns a byte array with UTF-8 format representation of the encoded SipMessage. * * @return byte array with UTF-8 format representation of the encoded SipMessage. */ public @NonNull byte[] toEncodedMessage() { byte[] header = new StringBuilder() .append(mStartLine) .append(mHeaderSection) .append(CRLF) .toString().getBytes(UTF_8); byte[] sipMessage = new byte[header.length + mContent.length]; System.arraycopy(header, 0, sipMessage, 0, header.length); System.arraycopy(mContent, 0, sipMessage, header.length, mContent.length); return sipMessage; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy